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 ToolTip提示效果
Jul 20 Javascript
JS等比例缩小图片尺寸的实例
Feb 27 Javascript
利用js 进行输入框自动匹配字符的小例子
Jun 29 Javascript
jQuery的显示和隐藏方法与css隐藏的样式对比
Oct 18 Javascript
Javascript动画的实现原理浅析
Mar 02 Javascript
JQuery球队选择实例
May 18 Javascript
8 行 Node.js 代码实现代理服务器
Dec 05 Javascript
jquery+html仿翻页相册功能
Dec 20 Javascript
令按钮悬浮在(手机)页面底部的实现方法
May 02 Javascript
layui前段框架日期控件使用方法详解
May 19 Javascript
如何修改Vue打包后文件的接口地址配置的方法
Apr 22 Javascript
Node使用koa2实现一个简单JWT鉴权的方法
Jan 26 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乱码问题,UTF-8乱码常见问题小结
2012/04/09 PHP
php使用多个进程同时控制文件读写示例
2014/02/28 PHP
PHP return语句另类用法不止是在函数中
2014/09/17 PHP
php文件类型MIME对照表(比较全)
2016/10/07 PHP
thinkPHP中验证码的简单实现方法
2016/12/05 PHP
php实现根据身份证获取精准年龄
2020/02/26 PHP
JS事件Event元素(兼容IE,Firefox,Chorme)
2012/11/01 Javascript
javascript生成不重复的随机数
2015/07/17 Javascript
javascript中Array()数组函数详解
2015/08/23 Javascript
分享javascript实现的冒泡排序代码并优化
2016/06/05 Javascript
JavaScript基础——使用Canvas绘图
2016/11/02 Javascript
JS变量及其作用域
2017/03/29 Javascript
js评分组件使用详解
2017/06/06 Javascript
JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)
2017/06/09 Javascript
基于jQuery的$.getScript方法去加载javaScript文档解析
2017/11/08 jQuery
实现jquery放大镜的两种方法
2018/02/22 jQuery
JS/jQuery实现简单的开关灯效果【案例】
2019/02/19 jQuery
vue history 模式打包部署在域名的二级目录的配置指南
2019/07/02 Javascript
element-ui 文件上传修改文件名的方法示例
2019/11/05 Javascript
vue element 关闭当前tab 跳转到上一路由操作
2020/07/22 Javascript
openlayers 3实现车辆轨迹回放
2020/09/24 Javascript
[06:07]刀塔密之二:攻之吾命受之吾幸
2014/07/03 DOTA
vscode 远程调试python的方法
2017/12/01 Python
PyQt5每天必学之进度条效果
2018/04/19 Python
python打开音乐文件的实例方法
2020/07/21 Python
全面介绍python中很常用的单元测试框架unitest
2020/12/14 Python
html5 Canvas实现图片旋转的示例
2018/01/15 HTML / CSS
高性能钓鱼服装:Huk Gear
2019/02/20 全球购物
Opodo意大利:欧洲市场上领先的在线旅行社
2019/10/24 全球购物
初二政治教学反思
2014/01/12 职场文书
经济类毕业生求职信
2014/06/26 职场文书
市委常委会班子党的群众路线教育实践活动整改方案
2014/10/25 职场文书
政协常委会议主持词
2015/07/03 职场文书
游戏开发中如何使用CocosCreator进行音效处理
2021/04/14 Javascript
深入理解python多线程编程
2021/04/18 Python
mysql连接查询中and与where的区别浅析
2021/07/01 MySQL