10月阅读周·JavaScript异步编程设计快速响应的网络应用:用Promise对象代替回调函数
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》。
当前阅读周书籍:《JavaScript异步编程设计快速响应的网络应用》。
用Promise对象代替回调函数
理想情况下,开始执行异步任务的任何函数都应该返回Promise对象。遗憾的是,大多数JavaScript API(包括所有浏览器及Node.js均使用的那些原生函数)都基于回调函数,而不是基于Promise对象。在本节中,我们将看到如何在基于回调函数的API中使用Promise对象。
在基于回调函数的API中使用Promise对象的最直接的方法是,生成一个Deferred对象并传递其触发器函数作为API的回调参数。例如,我们可以把Deferred对象的resolve方法传递给一个像setTimeout这样的简单异步函数。
var timing = new $.Deferred();
setTimeout(timing.resolve, 500);
考虑到API可能会出错,我们还要写一个根据情况指向 resolve 或reject的回调函数。例如,我们会这样写Node风格的回调:
var fileReading = new $.Deferred();
fs.readFile(filename, 'utf8', function (err) {
if (err) {
fileReading.reject(err);
} else {
fileReading.resolve(Array.prototype.slice.call(arguments, 1));
}
});
(没错,确实能在Node中使用jQuery。只要运行命令行npm install jquery即可,其用法和其他所有模块一样。还有一个库叫Standalone Deferred,它独立实现了jQuery风格的Promise。
总这么写很麻烦,所以何不写一个工具函数以根据任何给定Deferred对象来生成Node风格的回调呢?
deferredCallback = function (deferred) {
return function (err) {
if (err) {
deferred.reject(err);
} else {
deferred.resolve(Array.prototype.slice.call(arguments, 1));
}
};
};
有了这个工具函数,前面那个例子就可以写成这样:
var fileReading = new $.Deferred();
fs.readFile(filename, 'utf8', deferredCallback(fileReading));
Q.js的Deferred对象为此提供了一个现成的node方法:
var fileReading = Q.defer();
fs.readFile(filename, 'utf8', fileReading.node());
随着Promise越来越流行,会有越来越多的JavaScript库循着jQuery的脚步,要求其异步函数必须返回Promise对象。到那时,只需要几行代码就能将想用的任何异步函数转变成Promise对象的生成函数。
总结
Promise 大大有助于让意面式的回调趋于平滑(富含Ajax 调用的应用通常充斥着这些如意大利面条般纠缠在一起的回调),而且也是因为Promise可以非常轻松地协调各种类型的异步任务。
运用Promise需要一些实践经验,特别是使用 pipe 时,不过这是非常值得培养的一种习惯。你可以在此窥见 JavaScript 的未来。返回Promise对象的JavaScriptAPI越多,这些API就越有吸引力。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)