把JScript函数模拟为"异步执行"方式

简介:

 我们知道"同步"和"异步"这个概念主要是对线程来说的,这里怎么能把JScirpt的函数弄成异步方式来执行呢?! 这样做又有什么意义呢?


    当我们使用JScript来操作DHMTL元素的时候,DHTML元素的可视更新是和脚本的执行作用域有关的,也就是说脚本的执行是必须"间断"的,从而让IE的从message pump里拿到onpaint事件消息,否则DHTML属性变化引起的的可视化更新并不会马上发生。前面说的"间断"不是真正意义上的程序中断,而是脚本执行的一个作用域的变化。

    举个例子来说,如果我们使用下面的JScript语句,我们是不可能模拟出文字变大的动态效果的。

< script >
function  foo(elmt)

    
var  fontSize  =   10 ;
    
for  (  var  i = 0  ; i  <   10  ;  ++ i )
    
{
         fontSize 
+=   10 ;
         aDiv.style.fontSize 
=  fontSize;
         dtBegin 
=   new  Date();
         
do {;} while (( new  Date()) - dtBegin  <   500 );
    }
 
}
 
</ script >
< button  onclick ="foo(this)" >Click </ button >
< div  id ="aDiv" >font size </ div >

   问题就是脚本执行在这个函数中始终没有离开它的域,IE根本不会在fontSize改变的过程中重绘,而只能在执行10次循环后,显示出fontSize为110的文字(需要注意这里的矛盾并不是那个do while的延时循环,它只是耗点CPU而已)。

   那么这种效果怎么来做呢?必须使用setInterval或者setTimeout来实现,这两个函数将为脚本执行开启新的"线程",不过这些线程也是会block的,而不是真正的多线程的线程,否这就更乱套了,我们也不需要脚本支持广义上的异步执行。下面我这个"异步执行"的函数也就是基于setTimeout的特性来做的。

< html >
< body >
     < button  onclick ="foo(this)" >
        Click </ button >
     < div  id ="aDiv" >
        font size </ div >
     < table >
         < tbody >
             < tr >
                 < td >
                     < button  onclick ="__doHeavyWork" >
                        Heavy Work 1 </ button >
                 </ td >
                 < td  rowspan ="2" >
                     < span  id ="info" ></ span >
                 </ td >
             </ tr >
             < tr >
                 < td >
                     < button  onclick ="doHeavyWork" >
                        Heavy Work 2 </ button >
                 </ td >
             </ tr >
         </ tbody >
     </ table >
     < script  language ="javascript" >
function  doHeavyWork(elmt)
{
    __doHeavyWork.args 
=  [];
    __doHeavyWork.args.push(elmt);
    info.innerText 
=  'begin';
    window.setTimeout(__doHeavyWork, 
1 );
}


function  __doHeavyWork(elmt)
{
    
if  (  ! elmt )
    

        elmt 
=  __doHeavyWork.args[ 0 ];
    }

    
var  dtBegin  =   new  Date();
    
do
    
{
        
var  a  =   1 + 1 ;
    }

    
while (( new  Date()) - dtBegin  <   2000  );
    info.innerText 
=  elmt.tagName  +  ': mession complete.'
}

 
</ script >
</ body >
</ html >

   点击"Heavy Work 1"按钮,我们是看不到浏览器里面出现"Begin..."的提示的,而只能在最后看到一个"BUTTOM: mession complete."。而点击"Heavy Work 2"按钮,就能看到"Begin..."提示,当任务完成再显示"... complete."。这里使用setTimeout是很常见的了,不过有个小hack,我们可以把原函数的参数通过Function对象(就是大写的Function)带到__doHeavyWork函数中去。上例中我自己建了一个args数组对象来存放参数,因为setTimeout里面只能写函数名,没有办法带参数的,到了__doHeavyWork里,再把args里的参数取出,这样的好处是让代码变得内聚性很强,而不需要全局变量来cache doHeavyWork和__doHeavyWork之间的参数。

   正是由于这里的__doHeavyWork是通过setTimeout后的Timer来启动执行的,已经和doHeavyWork不在同一个域中了,所以我们的info.innerText = 'begin...';在doHeavyWork完成后就会立即显示执行效果,而不会因为函数的流程而block。同时当__doHeavyWork执行后,他又会在自己的域中block起来,所以我说这个"异步执行"方式是引号扩起来的,而不是真正的多线程的异步。

   合理的使用这种JScript函数模拟"异步执行"的方式,可以让复杂的网页,特别是无刷性的网页表现出更好的可视效果。


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

目录
相关文章
|
7月前
|
前端开发 JavaScript 数据处理
在JavaScript中,什么是异步函数执行的例子
在JavaScript中,什么是异步函数执行的例子
33 0
|
6月前
|
前端开发 JavaScript 数据处理
在JavaScript中,异步函数是指那些不会立即执行完毕,而是会在未来的某个时间点(比如某个操作完成后,或者某个事件触发后)才完成其执行的函数
【6月更文挑战第15天】JavaScript中的异步函数用于处理非同步任务,如网络请求或定时操作。它们使用回调、Promise或async/await。
57 7
|
5月前
|
数据采集 JavaScript 前端开发
NodeJS技巧:在循环中管理异步函数的执行次数
在Node.js网络爬虫开发中,管理异步函数执行次数是关键。利用Promise.all、async/await或async库能优雅地控制并发。示例展示如何用async/await配合代理IP抓取数据,避免触发反爬策略。在循环中,每个异步请求只执行一次,保证请求有序进行,提高爬虫的稳定性和效率。通过正确的方法,可以有效应对网络爬虫的挑战。
NodeJS技巧:在循环中管理异步函数的执行次数
|
4月前
|
Go 数据库 UED
[go 面试] 同步与异步:程序执行方式的不同之处
[go 面试] 同步与异步:程序执行方式的不同之处
|
7月前
|
JavaScript 前端开发
JavaScript自执行函数:用途、好处
JavaScript自执行函数:用途、好处
148 6
|
7月前
|
前端开发 JavaScript 数据处理
在JavaScript中,异步函数是指什么
【5月更文挑战第9天】JavaScript中的异步函数用于处理非立即完成的操作,如定时器、网络请求等。它们可通过回调函数、Promise或async/await来实现。示例展示了如何使用async/await模拟网络请求:定义异步函数fetchData返回Promise,在另一异步函数processData中使用await等待结果并处理。当fetchData的Promise解析时,data变量接收结果并继续执行后续代码。注意,调用异步函数不会阻塞执行,而是会在适当时间点继续。
44 0
|
7月前
|
开发框架 JavaScript 前端开发
描述JavaScript事件循环机制,并举例说明在游戏循环更新中的应用。
JavaScript的事件循环机制是单线程处理异步操作的关键,由调用栈、事件队列和Web APIs构成。调用栈执行函数,遇到异步操作时交给Web APIs,完成后回调函数进入事件队列。当调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中常用框架提供更高级别的抽象。
44 1
|
7月前
|
JavaScript 前端开发
js函数:函数是JS的基本组成单元,用于封装代码块以实现特定功能。理解函数的定义、调用和参数传递方式非常重要。具体案例详解
js函数:函数是JS的基本组成单元,用于封装代码块以实现特定功能。理解函数的定义、调用和参数传递方式非常重要。具体案例详解
68 1
|
监控 Go
Go 语言一次性定时器使用方式和实现原理
Go 语言一次性定时器使用方式和实现原理
83 0
|
Web App开发 自然语言处理 JavaScript
带你读《现代Javascript高级教程》十、JavaScript引擎的工作原理:代码解析与执行(1)
带你读《现代Javascript高级教程》十、JavaScript引擎的工作原理:代码解析与执行(1)