10月阅读周·JavaScript异步编程设计快速响应的网络应用:Promise 回调篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》。
当前阅读周书籍:《JavaScript异步编程设计快速响应的网络应用》。
Promise 回调
Promise 向回调传递数据
Promise 对象可以向其回调提供额外的信息。举个例子,下面这两个Ajax代码片段是等效的。
// 直接使用回调
$.get(url, successCallback);
// 将回调绑定至Promise 对象
var fetchingData = $.get(url);
fetchingData.done(successCallback);
执行或拒绝 Deferred 对象时,提供的任何参数都会转发至相应的回调。
var aDreamDeferred = new $.Deferred();
aDreamDeferred.done(function (subject) {
console.log('I had the most wonderful dream about', subject);
});
aDreamDeferred.resolve('the JS event model');
还有一些特殊的方法能实现在特定上下文中运行回调(即将this设置为特定的值):resolveWith 和 rejectWith。此时只需传递上下文环境作为第一个参数,同时以数组的形式传递所有其他参数。
var slashdotter = {
comment: function (editor) {
console.log('Obviously', editor, 'is the best text editor.');
},
};
var grammarDeferred = new $.Deferred();
grammarDeferred.done(function (verb, object) {
this[verb](object);
});
grammarDeferred.resolveWith(slashdotter, ['comment', 'Emacs']);
然而,将参数打包成数组是很痛苦的。所以还有一个小窍门:不再使用 resolveWith/rejectWith,而是直接在目标上下文中调用resolve/ reject 方法,这是因为resolve/reject 可以直接将其上下文环境传递至自己所触发的回调。因此,对于前面那个例子,使用以下代码亦可得到同样的结果。
grammarDeferred.resolve.call(slashdotter, 'comment', 'Emacs');
进度通知
Promise 对象是你希望任务结束时发生的一些事。但是,你没听说过过程和结果同样重要吗?难道你不以为然吗?
幸好,jQuery 团队意识到了这一点并遵守 Promises/A 规范,于是在jQuery 1.7 中为 Promise 对象新添了一种可以调用无数次的回调。这个回调叫做progress(进度)。举个例子,假设有人正在奋力达成美国全国小说写作月(National Novel Writing Month,简写为NaNoWriMo)
项目设定的日均码字目标,而我们希望更新一个指示器以反映他距离实现这个目标还有多远。
var nanowrimoing = $.Deferred();
var wordGoal = 5000;
nanowrimoing.progress(function (wordCount) {
var percentComplete = Math.floor((wordCount / wordGoal) * 100);
$('#indicator').text(percentComplete + '% complete');
});
nanowrimoing.done(function () {
$('#indicator').text('Good job!');
});
Deferred对象的nanowrimoing准备就绪之后,可以像下面这样对字数的变化作出响应。
$('#document').on('keypress', function () {
var wordCount = $(this).val().split(/\s+/).length;
if (wordCount >= wordGoal) {
nanowrimoing.resolve();
}
nanowrimoing.notify(wordCount);
});
Deferred 对象的 notify(通知)调用会调用我们设定的 progress回调。就像resolve和reject一样,notify也能接受任意参数。请注意,一旦执行了 nanowrimoing 对象,则再作 nanowrimoing.notify调用将不会有任何反应,这就像任何额外的resolve调用及reject调用也会被直接无视一样。
总结
Promise 对象接受 3 种回调形式:done、fail 和progress。执行Promise对象时,运行的是done回调;拒绝Promise对象时,运行的是fail回调;对处于挂起状态的Deferred对象调用notify时,运行的是progress回调。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)