JavaScript 异步调用框架 (Part 1 - 问题 & 场景)


Posted in Javascript onAugust 03, 2009

问题
在Ajax应用中,调用XMLHttpRequest是很常见的情况。特别是以客户端为中心的Ajax应用,各种需要从服务器端获取数据的操作都通过XHR异步调用完成。然而在单线程的JavaScript编程中,XHR异步调用的代码风格实在是与一般的JavaScript代码格格不入。

额外参数
考虑一个除法函数,如果它是纯客户端的同步函数,那么签名会是这样的:

function divide(operand1, operand2)

然而假设我们对客户端除法的精度不满意,于是把除法转移到服务器端来执行,那么它是个需要调用XHR的异步函数,签名也就可能会是以下几种之一:

function divide(operand1, operand2, callback) 
function divide(operand1, operand2, successCallback, failureCallback) 
function divide(operand1, operand2, options)

我们必须在签名中引入新的参数来传递回调函数,不能选择让函数变成阻塞式的同步调用。

可传递性
不仅仅直接操作XHR的函数需要引入新的参数,这种复杂性还会顺着调用栈向外传递。例如说,我们对加减乘除四则运算作了封装,只向外暴露一个运算接口:

function calculate(operand1, operand2, operator)

这个calculate函数根据operator参数来调用内部的plus, subtract, multiply, divide函数。然而,因为divide函数变成了异步函数,所以整个calculate函数不得不也转变为异步函数:

function calculate(operand1, operand2, operator, callback)

同时,在调用栈之上凡是需要调用到calculate的函数,都必须变成异步的,除非它并不需要向上一级调用函数返回结果。

同步并存
尽管calculate函数变成了一个异步函数,它所调用的plus, subtract, multiply函数还是同步函数,只有调用divide时是异步的,这时候calculate就是一个异步同步并存函数。

这会带来什么问题?calculate的调用者看到函数签名自然会认为calculate是个异步函数,因为它需要传递回调函数,然而calculate的执行方式却是不确定的。考虑如下调用:

calculate(operand1, operand2, operator, callback);
next();

这里涉及到callback和next两个函数,它们哪个先执行哪个后执行是不确定的,或者说是依赖于calculate具体实现的。

如果calculate的实现是,当不需要进行异步操作时,直接调用callback。那么,在执行加减乘法时callback会在next之前被调用;在执行除法时next会在callback之前调用。

如果我们不喜欢这种不确定性,我们可以改变一下calculate的实现,把同步调用也都改为setTimeout形式的,这样在任何情况下next都一定会在callback之前被调用。

然而后面一种做法依赖于成本较高的实现方式,开发者一个不小心(或者摆明偷懒)就会漏掉setTimeout,导致函数调用顺序变得不确定,所以我们会希望这是框架帮助实现的功能,在使用框架时无法把这绕过。

场景
在这里,我举一个关于上述问题的具体应用场景。(为简化问题,描述已略作修改,与实际应用并不一致。)

在百度Hi网页版里面,我们会在客户端保存一个用户对象列表,在打开和这个用户的聊天窗口时,我们需要从中读取这个用户的信息。这个操作就涉及很多可能同步又可能异步的分支:

用户对象未缓存
异步读取用户信息
用户对象已缓存
用户是好友(信息更新会由服务器端推送)
同步读取用户信息
用户不是好友(信息更新需要由客户端拉取)
可以接受缓存信息
同步读取用户信息
必须获取最新信息
异步读取用户信息
可以看到,分支的结果最终既有同步的,也有异步的。并且这些分支还不是在一个函数里完成,而是在几个函数里实现。也就是说,按照传统的模式,这些函数一部分是同步的,一部分是异步的,由于异步的传递性,最终调用栈顶层的函数都是异步的。

为了解决这个问题,我们需要写一个异步调用框架,用一种统一的方式来进行调用,把同步和异步调用都合并为一种返回方式。

Javascript 相关文章推荐
兼容Mozilla必须知道的知识。
Jan 09 Javascript
jquery插件 cluetip 关键词注释
Jan 12 Javascript
javascript实现TreeView 无刷新展开的实例代码
Jul 13 Javascript
Mac/Windows下如何安装Node.js
Nov 22 Javascript
js实现的GridView即表头固定表体有滚动条且可滚动
Feb 19 Javascript
JS简单生成两个数字之间随机数的方法
Aug 03 Javascript
jQuery+vue.js实现的九宫格拼图游戏完整实例【附源码下载】
Sep 12 jQuery
vue组件中的数据传递方法
May 14 Javascript
vue和webpack打包项目相对路径修改的方法
Jun 15 Javascript
echarts整合多个类似option的方法实例
Jul 10 Javascript
Vue项目自动转换 px 为 rem的实现方法
Oct 29 Javascript
react实现复选框全选和反选组件效果
Aug 25 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
Javascript 汉字字节判断
Aug 01 #Javascript
You might like
php+jquery编码方面的一些心得(utf-8 gb2312)
2010/10/12 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十)
2014/06/24 PHP
php实现多维数组排序的方法示例
2017/03/23 PHP
新闻内页-JS分页
2006/06/07 Javascript
用JavaScript实现仿Windows关机效果
2007/03/10 Javascript
juqery 学习之五 文档处理 包裹、替换、删除、复制
2011/02/11 Javascript
为开发者准备的10款最好的jQuery日历插件
2014/02/04 Javascript
Javascript中使用A标签获取当前目录的绝对路径方法
2015/03/02 Javascript
js实现的星星评分功能函数
2015/12/09 Javascript
学习jQuey中的return false
2015/12/18 Javascript
解析JavaScript实现DDoS攻击原理与保护措施
2016/12/26 Javascript
jQuery操作json常用方法示例
2017/01/04 Javascript
微信小程序 数组(增,删,改,查)等操作实例详解
2017/01/05 Javascript
axios中cookie跨域及相关配置示例详解
2017/12/20 Javascript
p5.js实现斐波那契螺旋的示例代码
2018/03/22 Javascript
Js实现复选框的全选、全不选反选功能代码实例
2020/02/28 Javascript
在Vue中使用Select选择器拼接label的操作
2020/10/22 Javascript
[04:45]DOTA2上海特级锦标赛主赛事第四日RECAP
2016/03/06 DOTA
[04:44]DOTA2 2017全国高校联赛视频回顾
2017/08/21 DOTA
Python基于Tkinter的HelloWorld入门实例
2015/06/17 Python
Python3如何对urllib和urllib2进行重构
2019/11/25 Python
基于Django实现日志记录报错信息
2019/12/17 Python
Python3合并两个有序数组代码实例
2020/08/11 Python
利用CSS的Sass预处理器(框架)来制作居中效果
2016/03/10 HTML / CSS
HTML中使用SVG与SVG预定义形状元素介绍
2013/06/28 HTML / CSS
Trip.com香港网站:Ctrip携程旗下,全球最大的网上旅游社之一
2016/08/01 全球购物
澳大利亚优惠网站:Deals.com.au
2019/07/02 全球购物
西门豹教学反思
2014/02/04 职场文书
收银出纳员岗位职责
2014/02/23 职场文书
毕业寄语大全
2014/04/09 职场文书
人力资源管理毕业生自荐信
2014/06/26 职场文书
美德少年事迹材料500字
2014/08/19 职场文书
重阳节简报
2015/07/20 职场文书
毕业班工作总结
2015/08/10 职场文书
我的中国梦主题班会
2015/08/14 职场文书
2016年区委书记抓基层党建工作公开承诺书
2016/03/25 职场文书