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 相关文章推荐
combox改进版 页面原型参考dojo的,比网上jQuery的那些combox功能强,代码更小
Apr 15 Javascript
不使用中间变量,交换int型的 a, b两个变量的值。
Oct 29 Javascript
如何使用PHP+jQuery+MySQL实现异步加载ECharts地图数据(附源码下载)
Feb 23 Javascript
Bootstrap分页插件之Bootstrap Paginator实例详解
Oct 15 Javascript
jquery实现超简单的瀑布流布局【推荐】
Mar 08 Javascript
JavaScript通过改变文字透明度实现的文字闪烁效果实例
Apr 27 Javascript
JS实现的找零张数最小问题示例
Nov 28 Javascript
详解vue项目中如何引入全局sass/less变量、function、mixin
Jun 02 Javascript
如何让node运行es6模块文件及其原理详解
Dec 11 Javascript
vue 虚拟DOM的原理
Oct 03 Javascript
JS实现简单贪吃蛇小游戏
Oct 28 Javascript
jQuery实现购物车全功能
Jan 11 jQuery
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
php feof用来识别文件末尾字符的方法
2010/08/01 PHP
php调用方法mssql_fetch_row、mssql_fetch_array、mssql_fetch_assoc和mssql_fetch_objcect读取数据的区别
2012/08/08 PHP
PHP中date与gmdate的区别及默认时区设置
2014/05/12 PHP
PHP实现登陆表单提交CSRF及验证码
2017/01/24 PHP
Laravel 中使用 Vue.js 实现基于 Ajax 的表单提交错误验证操作
2017/06/30 PHP
JS array 数组详解
2009/03/22 Javascript
jQuery+CSS 实现的超Sexy下拉菜单
2010/01/17 Javascript
常见效果实现之返回顶部(结合淡入、淡出、减速滚动)
2012/01/04 Javascript
jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
2016/01/22 Javascript
D3.js实现折线图的方法详解
2016/09/21 Javascript
使用JS和canvas实现gif动图的停止和播放代码
2017/09/01 Javascript
nodejs async异步常用函数总结(推荐)
2017/11/17 NodeJs
在vue项目中使用element-ui的Upload上传组件的示例
2018/02/08 Javascript
深入理解javascript prototype的相关知识
2019/09/19 Javascript
JavaScript基于面向对象实现的无缝滚动轮播示例
2020/01/17 Javascript
Vue data的数据响应式到底是如何实现的
2020/02/11 Javascript
浅谈Ant Design Pro 菜单自定义 icon
2020/11/17 Javascript
Python中用Decorator来简化元编程的教程
2015/04/13 Python
浅析Python中的for 循环
2016/06/09 Python
Python的SQLalchemy模块连接与操作MySQL的基础示例
2016/07/11 Python
Python更新数据库脚本两种方法及对比介绍
2017/07/27 Python
Python实现k-means算法
2018/02/23 Python
python3 中文乱码与默认编码格式设定方法
2018/10/31 Python
python多线程+代理池爬取天天基金网、股票数据过程解析
2019/08/13 Python
django 快速启动数据库客户端程序的方法示例
2019/08/16 Python
Python Numpy中数据的常用保存与读取方法
2020/04/01 Python
一款纯css3实现的鼠标经过按钮特效教程
2014/11/09 HTML / CSS
html5 web本地存储将取代我们的cookie
2012/12/26 HTML / CSS
html5 application cache遇到的严重问题
2012/12/26 HTML / CSS
德国大型箱包和皮具商店:Koffer
2019/10/01 全球购物
本科毕业自我鉴定
2014/03/20 职场文书
政风行风评议心得体会
2014/10/21 职场文书
学生检讨书怎么写
2015/05/07 职场文书
男人帮观后感
2015/06/18 职场文书
Django使用redis配置缓存的方法
2021/06/01 Redis
Java工作中实用的代码优化技巧分享
2022/04/21 Java/Android