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 相关文章推荐
window.onbeforeunload方法在IE下无法正常工作的解决办法
Jan 23 Javascript
JAVASCRIPT车架号识别/验证函数代码 汽车车架号验证程序
Jan 08 Javascript
JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(六)
Apr 07 Javascript
node.js实现BigPipe详解
Dec 05 Javascript
JavaScript仿支付宝密码输入框
Dec 29 Javascript
AngularJS中的过滤器filter用法完全解析
Apr 22 Javascript
jQuery树形控件zTree使用小结
Aug 02 Javascript
axios学习教程全攻略
Mar 26 Javascript
详解vue axios用post提交的数据格式
Aug 07 Javascript
详解angular应用容器化部署
Aug 14 Javascript
vue中使用heatmapjs的示例代码(结合百度地图)
Sep 05 Javascript
用React Native制作一个简单的游戏引擎
May 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 array_intersect比array_diff快(附详细的使用说明)
2011/07/03 PHP
php中并发读写文件冲突的解决方案
2013/10/25 PHP
php内核解析:PHP中的哈希表
2014/01/30 PHP
phpStudy中升级MySQL版本到5.7.17的方法步骤
2017/08/03 PHP
Jquery设置attr的disabled属性控制某行显示或者隐藏
2014/09/25 Javascript
js实现iframe自动自适应高度的方法
2015/02/17 Javascript
js判断手机号运营商的方法
2015/10/23 Javascript
AngularJs Injecting Services Into Controllers详解
2016/09/02 Javascript
js实现非常棒的弹出div
2016/10/06 Javascript
jQuery插件FusionCharts绘制2D环饼图效果示例【附demo源码】
2017/04/10 jQuery
Angular 2.0+ 的数据绑定的实现示例
2017/08/09 Javascript
深入理解Vue 组件之间传值
2018/08/16 Javascript
jquery实现弹窗(系统提示框)效果
2019/12/10 jQuery
JavaScript变量Dom对象的所有属性
2020/04/30 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
python里大整数相乘相关技巧指南
2014/09/12 Python
值得收藏,Python 开发中的高级技巧
2018/11/23 Python
使用Python的SymPy库解决数学运算问题的方法
2019/03/27 Python
Python 获取 datax 执行结果保存到数据库的方法
2019/07/11 Python
使用python实现学生信息管理系统
2021/02/25 Python
玩具反斗城美国官网:Toys"R"Us
2016/09/17 全球购物
世界上获奖最多的手机镜头:Olloclip
2018/03/03 全球购物
Tessabit美国:集世界奢侈品和设计师品牌的意大利精品买手店
2020/06/29 全球购物
Trench London官方网站:高级风衣和意大利皮夹克
2020/07/11 全球购物
linux面试题参考答案(10)
2016/10/26 面试题
学习保证书范文
2014/04/30 职场文书
2015新年寄语大全
2014/12/08 职场文书
学生党员检讨书范文
2014/12/27 职场文书
李强为自己工作观后感
2015/06/11 职场文书
婚礼父母致辞
2015/07/28 职场文书
2016年共产党员个人承诺书
2016/03/24 职场文书
《三国志》赏析
2019/08/27 职场文书
教师节作文之小学四年级
2019/09/03 职场文书
纯CSS实现酷炫的霓虹灯效果
2021/04/13 HTML / CSS
《王国之心》迎来了发售的20周年, 野村哲发布贺图
2022/04/11 其他游戏
基于Redission的分布式锁实战
2022/08/14 Redis