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 相关文章推荐
javascript 设置文本框中焦点的位置
Nov 20 Javascript
js过滤特殊字符输入适合输入、粘贴、拖拽多种情况
Mar 22 Javascript
JavaScript中如何通过arguments对象实现对象的重载
May 12 Javascript
jquery引用方法时传递参数原理分析
Oct 13 Javascript
原生js结合html5制作简易的双色子游戏
Mar 30 Javascript
JavaScript实现给定时间相加天数的方法
Jan 25 Javascript
全面理解JavaScript中的继承(必看)
Jun 16 Javascript
Express的HTTP重定向到HTTPS的方法
Jun 06 Javascript
React+Webpack快速上手指南(小结)
Aug 15 Javascript
vue element upload实现图片本地预览
Aug 20 Javascript
vue输入节流,避免实时请求接口的实例代码
Oct 30 Javascript
Vue中keep-alive 实现后退不刷新并保持滚动位置
Mar 17 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使用JSON和将json还原成数组
2015/02/12 PHP
PHP面试题之文件目录操作
2015/10/15 PHP
深入理解PHP中的empty和isset函数
2016/05/26 PHP
Thinkphp 空操作、空控制器、命名空间(详解)
2017/05/05 PHP
老生常谈php中传统验证与thinkphp框架(必看篇)
2017/06/10 PHP
JavaScript 拾漏补遗
2009/12/27 Javascript
创建公共调用 jQuery Ajax 带返回值
2012/08/01 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
2014/05/08 Javascript
浅谈javascript的调试
2015/01/28 Javascript
浅谈EasyUI中编辑treegrid的方法
2015/03/01 Javascript
一道关于JavaScript变量作用域的面试题
2016/03/08 Javascript
jQuery内存泄露解决办法
2016/12/13 Javascript
利用Vue.js实现求职在线之职位查询功能
2017/07/03 Javascript
详解微信小程序Radio选中样式切换
2017/07/06 Javascript
vue自定义指令directive实例详解
2018/01/17 Javascript
vue实现裁切图片同时实现放大、缩小、旋转功能
2018/03/02 Javascript
javascript 构建模块化开发过程解析
2019/09/11 Javascript
layui实现显示数据表格、搜索和修改功能示例
2020/06/03 Javascript
详解ES6实现类的私有变量的几种写法
2021/02/10 Javascript
Python的条件语句与运算符优先级详解
2015/10/13 Python
Java编程迭代地删除文件夹及其下的所有文件实例
2018/02/10 Python
python判断完全平方数的方法
2018/11/13 Python
Python装饰器限制函数运行时间超时则退出执行
2019/04/09 Python
PyQt5 对图片进行缩放的实例
2019/06/18 Python
pytorch方法测试详解——归一化(BatchNorm2d)
2020/01/15 Python
Python发送邮件实现基础解析
2020/08/14 Python
HTTP状态码详解
2021/03/18 杂记
FitFlop澳大利亚官网:英国符合人体工学的鞋类品牌
2017/06/05 全球购物
高中毕业自我鉴定范文
2013/10/02 职场文书
2014年高考决心书
2014/03/11 职场文书
爱我中华演讲稿
2014/05/20 职场文书
任命书模板
2014/06/04 职场文书
创先争优演讲稿
2014/09/15 职场文书
五年级下册复习计划
2015/01/19 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
使用scrapy实现增量式爬取方式
2022/06/21 Python