JavaScript 异步调用框架 (Part 2 - 用例设计)


Posted in Javascript onAugust 03, 2009

传递回调
我们首先要考虑的一个问题是,如何传递回调入口。在最传统的XHR调用当中,回调函数会被作为最后一个参数传递给异步函数:

function asyncOperation(argument, callback)

在参数相当多的时候,我们可以把参数放到一个JSON里面,这样参数就如同具名参数一样,可以通过参数名选择性的传递参数,不传递的参数相当于使用默认值。这是从Prototype开始就流行起来的做法:
function asyncOperation(argument, options)

然而这两种做法都有一个坏处,就是把同步函数改为异步函数(或同步异步混合函数)时,必须显式地修改函数签名,在最后增加一个(或多个)参数。

由于在调用栈的底层引入异步函数对我们来说太常见了,为此可能要更改一大堆上层调用函数签名的成本实在是太高了,所以我们还是想一个不用修改函数签名的做法吧。

在这里我参考了.NET Framework的IAsyncResult设计,把异步操作有关的一切信息集中到一个对象上来,从而避免了对函数签名的修改。在此,我们假设一个异步函数的调用原型是这样子的:

function asyncOperation(argument) { 
operation = new Async.Operation(); 
setTimeout(function() { operation.yield("hello world"); }, 1000); 
return operation; 
}

在这段代码里,我们返回了一个Operation对象,用于将来传递回调函数。同时,我们通过setTimeout模拟了异步返回结果,而具体的返回方式就是yield方法。

接着,我们还要设计传递回调函数的方法。由于我们不能好像C#那样重载+=运算符,所以只能用函数传递回调函数:

var operation = asyncOperation(argument); 
operation.addCallback(function(result) { alert(result); });

在C#里面做这样的设计是不安全的,因为在异步操作可能在添加回调之前就完成了。但在JavaScript里面这样写是安全的,因为JavaScript是单线程的,紧接着asyncOperation的同步addCallback必然先执行,asyncOperation中的异步yield必然后执行。

调用顺序
可能有人要问,如果用户使用同步的方式来调用yield,这时候执行顺序不一样依赖于yield的实现吗?没错,不过yeild是在框架中一次性实现的,我们只要把它做成异步的就可以了,这样即使对它进行同步调用,也不影响执行顺序:

function psudoAsyncOperation(argument) { 
operation = new Async.Operation(); 
operation.yield("hello world"); 
return operation; 
} 
var operation = asyncOperation(argument); 
operation.addCallback(function(result) { alert(result); });

就算把代码写成这个样子,我们也能确保addCallback先于yield的实际逻辑执行。

事后回调
有时候,框架的使用者可能真的写出了先yield后addCallback的代码。这时候,我认为必须保证addCallback中添加的回调函数会被立即触发。因为用户添加这个回调函数,意味着他期望当异步操作有结果时通知这个回调函数,而这与添加回调函数时异步操作是否完成无关。为此,我们再添加一个用例:

function psudoAsyncOperation(argument) { 
operation = new Async.Operation(); 
operation.yield("hello world"); 
return operation; 
} 
var operation = asyncOperation(argument); 
setTimeout(function() { 
operation.addCallback(function(result) { alert(result); }); 
}, 1000);

小结
到这里,我们就设计好了一个名为Async.Operation的异步操作对象,具体如何实现关键的yield方法和addCallback方法将在下一篇文章讲述如果。
Javascript 相关文章推荐
jquery jqPlot API 中文使用教程(非常强大的图表工具)
Aug 15 Javascript
JS中typeof与instanceof之间的区别总结
Nov 14 Javascript
简介JavaScript中用于处理正切的Math.tan()方法
Jun 15 Javascript
详解JavaScript编程中正则表达式的使用
Oct 25 Javascript
Bootstrap的modal拖动效果
Dec 25 Javascript
jQuery仿IOS弹出框插件
Feb 18 Javascript
jQuery实现鼠标跟随效果
Feb 20 Javascript
bootstrap datetimepicker日期插件超详细使用方法介绍
Feb 23 Javascript
Angular2入门教程之模块和组件详解
May 28 Javascript
微信通过页面(H5)直接打开本地app的解决方法
Sep 09 Javascript
bootstrap Table的一些小操作
Nov 01 Javascript
vue proxy 的优势与使用场景实现
Jun 15 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
Javascript 验证上传图片大小[客户端]
Aug 01 #Javascript
You might like
PHILIPS L4X25T电路分析和打理
2021/03/02 无线电
phpmyadmin的#1251问题
2006/11/25 PHP
discuz的php防止sql注入函数
2011/01/17 PHP
Codeigniter校验ip地址的方法
2015/03/21 PHP
laravel批量生成假数据的方法
2019/10/09 PHP
JavaScript进阶教程(第四课第一部分)
2007/04/05 Javascript
JavaScript读取中文cookie时的乱码问题的解决方法
2009/10/14 Javascript
JavaScript基础知识之数据类型
2012/08/06 Javascript
js实现的类似于asp数据字典的数据类型代码实例
2014/09/03 Javascript
使用javascript提交form表单方法汇总
2015/06/25 Javascript
js传值后台中文出现乱码的解决方法
2016/06/30 Javascript
JS去掉字符串前后空格或去掉所有空格的用法
2017/03/25 Javascript
JavaScript实现滑动导航栏效果
2017/08/30 Javascript
ES6解构赋值的功能与用途实例分析
2017/10/31 Javascript
基于Vue实现关键词实时搜索高亮显示关键词
2018/07/21 Javascript
Angular2 自定义表单验证器的实现方法
2018/12/14 Javascript
Vue 之孙组件向爷组件通信的实现
2019/04/23 Javascript
Vue的双向数据绑定实现原理解析
2020/02/17 Javascript
JavaScript canvas绘制渐变颜色的矩形
2020/02/18 Javascript
VUE页面中通过双击实现复制表格中内容的示例代码
2020/06/11 Javascript
[43:41]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
Python HTMLParser模块解析html获取url实例
2015/04/08 Python
python实现将文本转换成语音的方法
2015/05/28 Python
python实现SMTP邮件发送功能
2020/06/16 Python
Python实现读取字符串按列分配后按行输出示例
2018/04/17 Python
Windows 安装 Anaconda3+PyCharm的方法步骤
2019/06/13 Python
Python中print函数简单使用总结
2019/08/05 Python
Python读写文件模式和文件对象方法实例详解
2019/09/17 Python
python实现的汉诺塔算法示例
2019/10/23 Python
墨西哥购物网站:Elektra
2020/01/21 全球购物
PHP如何设置和取得Cookie值
2015/06/30 面试题
部队党性分析材料
2014/02/16 职场文书
数学教学随笔感言
2014/02/17 职场文书
2019财务转正述职报告
2019/06/27 职场文书
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
2022/04/20 MySQL