JavaScript 异步调用框架 (Part 3 - 代码实现)


Posted in Javascript onAugust 04, 2009

类结构
首先我们来搭一个架子,把需要用到的似有变量都列出来。我们需要一个数组,来保存回调函数列表;需要一个标志位,来表示异步操作是否已完成;还可以学IAsyncResult,加一个state,允许异步操作的实现者对外暴露自定义的执行状态;最后加一个变量保存异步操作结果。

Async = { 
Operation: { 
var callbackQueue = []; 
this.result = undefined; 
this.state = "waiting"; 
this.completed = false; 
} 
}

addCallback方法
接下来,我们要实现addCallback方法,它的工作职责很简单,就是把回调函数放到callbackQueue中。此外,如果此时completed为true,说明异步操作已经yield过了,则立即调用此回调。
this.yield = function(callback) { 
callbackQueue.push(callback); 
if (this.completed) { 
this.yield(this.result); 
} 
return this; 
}

我们假设yield方法会把callbackQueue中的回调函数逐个取出来然后调用,因此如果compeleted为true,则使用已有的result再调用一次yield就可以了,这样yield自然会调用这次添加到callbackQueue的回调函数。
至于最后的return this;,只是为了方便jQuery风格的链式写法,可以通过点号分隔连续添加多个回调函数:
asyncOperation(argument) 
.addCallback(firstCallback) 
.addCallback(secondCallback);

yield方法
最后,我们要实现yield方法。它需要将callbackQueue中的回调函数逐个取出来,然后都调用一遍,并且保证这个操作是异步吧。
this.yield = function(result) { 
var self = this; 
setTimeout(function() { 
self.result = result; 
self.state = "completed"; 
self.completed = true; 
while (callbackQueue.length > 0) { 
var callback = callbackQueue.shift(); 
callback(self.result); 
} 
}, 1); 
return this; 
}

通过使用setTimeout,我们确保了yield的实际操作是异步进行的。然后我们把用户传入yield的结果及相关状态更新到对象属性之上,最后遍历callbackQueue调用所有的回调函数。
小结
这样我们就做好了一个简单的JavaScript异步调用框架,完整的代码可以看这里:异步调用框架Async.Operation。
这个框架能够很好的解决调用栈中出现同步异步操作并存的情况,假设所有函数都返回Async.Operation,框架的使用者可以使用一种统一的模式来编写代码,处理函数返回,而无需关心这个函数实际上是同步返回了还是异步返回了。
对于串行调用多个异步函数的情况,我们现在可以用嵌套addCallback的方式来书写,但随着嵌套层数的增多,代码会变得越来越不美观:
firstAsyncOperation().addCallback(function() { 
secondAsyncOperation().addCallback(function() { 
thirdAsyncOperation().addCallback(function() { 
finalSyncOperation(); 
}); 
}); 
});

我们能否把嵌套形式改为jQuery风格的链式写法呢?这是我们接下来要思考的问题,如果你不希望错过相关讨论的话
Javascript 相关文章推荐
js trim函数 去空格函数与正则集锦
Nov 20 Javascript
基于javascript html5实现多文件上传
Mar 03 Javascript
全面介绍vue 全家桶和项目实例
Dec 27 Javascript
Vue瀑布流插件的使用示例
Sep 19 Javascript
Vue触发式全局组件构建的方法
Nov 28 Javascript
解决node-sass偶尔安装失败的方法小结
Dec 05 Javascript
Node.js如何对SQLite的async/await封装详解
Feb 14 Javascript
记录一次开发微信网页分享的步骤
May 07 Javascript
JavaScript常用内置对象用法分析
Jul 09 Javascript
KnockoutJS数组比较算法实例详解
Nov 25 Javascript
js利用iframe实现选项卡效果
Aug 09 Javascript
js实现扫雷源代码
Nov 27 Javascript
JavaScript 异步调用框架 (Part 2 - 用例设计)
Aug 03 #Javascript
JavaScript 异步调用框架 (Part 1 - 问题 & 场景)
Aug 03 #Javascript
jQuery 相关控件的事件操作分解
Aug 03 #Javascript
利用javascript实现一些常用软件的下载导航
Aug 03 #Javascript
jQuery 隔行换色 支持键盘上下键,按Enter选定值
Aug 02 #Javascript
一句话JavaScript表单验证代码
Aug 02 #Javascript
JavaScript 关键字屏蔽实现函数
Aug 02 #Javascript
You might like
PHP使用者状态管理功能的应用
2006/10/09 PHP
关于BIG5-HKSCS的解决方法
2007/03/20 PHP
使用PHP批量生成随机用户名
2008/07/10 PHP
php addslashes 利用递归实现使用反斜线引用字符串
2013/08/05 PHP
PHP生成器简单实例
2015/05/13 PHP
php邮件发送的两种方式
2020/04/28 PHP
php图形jpgraph操作实例分析
2017/02/22 PHP
php实现与python进行socket通信的方法示例
2017/08/30 PHP
php设计模式之装饰模式应用案例详解
2019/06/17 PHP
用AJAX返回HTML片段中的JavaScript脚本
2010/01/04 Javascript
JQuery自定义事件的应用 JQuery最佳实践
2010/08/01 Javascript
JQGrid的用法解析(列编辑,添加行,删除行)
2013/11/08 Javascript
node.js中的console.info方法使用说明
2014/12/09 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
jQuery获取URL请求参数的方法
2015/07/18 Javascript
JavaScript获取function所有参数名的方法
2015/10/30 Javascript
浅谈Jquery中Ajax异步请求中的async参数的作用
2016/06/06 Javascript
javascript常用的设计模式
2017/02/09 Javascript
深入理解React高阶组件
2017/09/28 Javascript
vue添加axios,并且指定baseurl的方法
2018/09/19 Javascript
js观察者模式的弹幕案例
2020/11/23 Javascript
Python 第一步 hello world
2009/09/25 Python
python中将字典形式的数据循环插入Excel
2018/01/16 Python
Python从使用线程到使用async/await的深入讲解
2018/09/16 Python
Python实现石头剪刀布游戏
2021/01/20 Python
matplotlib之属性组合包(cycler)的使用
2021/02/24 Python
html5 分层屏幕适配的方法
2018/03/16 HTML / CSS
20世纪40年代连衣裙和复古服装:The Seamstress Of Bloomsbury
2018/07/24 全球购物
伦敦最受欢迎的蛋糕店:Konditor & Cook
2019/11/01 全球购物
2014年社区植树节活动方案
2014/02/28 职场文书
《跟踪台风的卫星》教学反思
2014/04/10 职场文书
国际贸易求职信
2014/07/05 职场文书
自查自纠工作总结
2014/10/15 职场文书
超市员工管理制度
2015/08/06 职场文书
68句权威创业名言
2019/08/26 职场文书
python for循环赋值问题
2021/06/03 Python