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 相关文章推荐
setInterval,setTimeout与jquery混用的问题
Apr 08 Javascript
实测jquery data()如何存值
Aug 18 Javascript
利用jQuery及AJAX技术定时更新GridView的某一列数据
Dec 04 Javascript
浅谈js图片前端预览之filereader和window.URL.createObjectURL
Jun 30 Javascript
深入浅析JavaScript中的3DES
Aug 24 Javascript
JavaScript中关于for循环删除数组元素内容时出现的问题
Nov 21 Javascript
node.js(express)中使用Jcrop进行图片剪切上传功能
Apr 21 Javascript
解决VUEX刷新的时候出现数据消失
Jul 03 Javascript
浅析node Async异步处理模块用例分析及常用方法介绍
Nov 17 Javascript
js调用设备摄像头的方法
Jul 19 Javascript
解决Layui选择全部,换页checkbox复选框重新勾选的问题方法
Aug 14 Javascript
Vue——前端生成二维码的示例
Dec 19 Vue.js
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
re0第二季蕾姆被制作组打入冷宫!艾米莉亚女主扶正,原因唏嘘
2020/04/02 日漫
php简单静态页生成过程
2008/03/27 PHP
PHP SFTP实现上传下载功能
2017/07/26 PHP
js 处理URL实用技巧
2010/11/23 Javascript
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
2010/11/30 Javascript
js弹出的对话窗口永远保持居中显示
2012/12/15 Javascript
JS Map 和 List 的简单实现代码
2013/07/08 Javascript
JS判断字符串长度的5个方法(区分中文和英文)
2014/03/18 Javascript
wap图片滚动特效无css3元素纯js脚本编写
2014/08/22 Javascript
JS实现动态移动层及拖动浮层关闭的方法
2015/04/30 Javascript
javascript组合使用构造函数模式和原型模式实例
2015/06/04 Javascript
根据user-agent判断蜘蛛代码黑帽跳转代码(js版与php版本)
2015/09/14 Javascript
js检测用户输入密码强度
2015/10/22 Javascript
Bootstrap基本样式学习笔记之表单(3)
2016/12/07 Javascript
ES6字符串模板,剩余参数,默认参数功能与用法示例
2017/04/06 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
vue实现滑动到底部加载更多效果
2020/10/27 Javascript
VUE单页面切换动画代码(全网最好的切换效果)
2019/10/31 Javascript
基于html+css+js实现简易计算器代码实例
2020/02/28 Javascript
解决vue自定义指令导致的内存泄漏问题
2020/08/04 Javascript
jQuery实现tab栏切换效果
2020/12/22 jQuery
[01:45]绝对公平!DOTA2队长征召模式详解
2014/04/25 DOTA
[04:13]2018国际邀请赛典藏宝瓶Ⅱ饰品一览
2018/07/21 DOTA
python编程测试电脑开启最大线程数实例代码
2018/02/09 Python
Python比较配置文件的方法实例详解
2019/06/06 Python
Python使用random模块生成随机数操作实例详解
2019/09/17 Python
Python中实现输入超时及如何通过变量获取变量名
2020/01/18 Python
python中类与对象之间的关系详解
2020/12/16 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
全球领先美式家具品牌:Ashley爱室丽家居
2017/08/07 全球购物
全球最大的游戏市场:G2A
2018/07/05 全球购物
Java中的基本数据类型所占存储空间大小固定的吗
2012/02/15 面试题
自主招生自荐信
2013/12/08 职场文书
端午节活动策划方案
2014/03/09 职场文书
制药工程专业职业生涯规划范文
2014/03/10 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书