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所必须要知道的一些
Mar 07 Javascript
js遍历td tr等html元素
Dec 13 Javascript
jsp+javascript打造级连菜单的实例代码
Jun 14 Javascript
javascript获取form里的表单元素的示例代码
Feb 14 Javascript
javascript实现全角半角检测的方法
Jul 23 Javascript
jQuery+canvas实现的球体平抛及颜色动态变换效果
Jan 28 Javascript
浅谈EasyUI常用控件的禁用方法
Nov 09 Javascript
vue中引入第三方字体文件的方法示例
Dec 17 Javascript
微信小程序返回箭头跳转到指定页面实例解析
Oct 08 Javascript
微信小程序wxml列表渲染原理解析
Nov 27 Javascript
jQuery弹框插件使用方法详解
May 26 jQuery
element tree树形组件回显数据问题解决
Aug 14 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
允许phpmyadmin空密码登录的配置方法
2011/05/29 PHP
10个实用的PHP代码片段
2011/09/02 PHP
php cookie使用方法学习笔记分享
2013/11/07 PHP
PHP计算百度地图两个GPS坐标之间距离的方法
2015/01/09 PHP
PHP中new static() 和 new self() 的区别介绍
2015/01/09 PHP
php实现的通用图片处理类
2015/03/24 PHP
PHP 以POST方式提交XML、获取XML,解析XML详解及实例
2016/10/26 PHP
php插件Xajax使用方法详解
2017/08/31 PHP
PHP利用DWZ.CN服务生成短网址
2019/08/11 PHP
jquery 操作日期、星期、元素的追加的实现代码
2012/02/07 Javascript
js实现文件上传表单域美化特效
2015/11/02 Javascript
js字符串截取函数slice、substring和substr的比较
2016/05/17 Javascript
jQuery实现的选择商品飞入文本框动画效果完整实例
2016/08/10 Javascript
Bootstrap响应式侧边栏改进版
2016/09/17 Javascript
jQuery插件zTree实现清空选中第一个节点所有子节点的方法
2017/03/08 Javascript
Vue 项目代理设置的优化
2018/04/17 Javascript
JavaScript中变量提升与函数提升经典实例分析
2018/07/26 Javascript
Vue 实现手动刷新组件的方法
2019/02/19 Javascript
js实现一款简单踩白块小游戏(曾经很火)
2019/12/02 Javascript
vue项目实现多语言切换的思路
2020/09/17 Javascript
python重试装饰器示例
2014/02/11 Python
python根据给定文件返回文件名和扩展名的方法
2015/03/27 Python
Python中List.count()方法的使用教程
2015/05/20 Python
python opencv实现图片旋转矩形分割
2018/07/26 Python
PySide和PyQt加载ui文件的两种方法
2019/02/27 Python
利用python开发app实战的方法
2019/07/09 Python
浅析pandas 数据结构中的DataFrame
2019/10/12 Python
Python通过两个dataframe用for循环求笛卡尔积
2020/04/29 Python
P D PAOLA法国官网:西班牙著名的珠宝首饰品牌
2020/02/15 全球购物
优乐美广告词
2014/03/14 职场文书
3分钟演讲稿
2014/04/30 职场文书
2014广电局实施党的群众路线教育实践活动方案思想汇报
2014/09/22 职场文书
七年级地理教学计划
2015/01/22 职场文书
旷工辞退通知书
2015/04/17 职场文书
检察院起诉意见书
2015/05/20 职场文书
2015年语文教师工作总结
2015/05/25 职场文书