JavaScript Promise迷你书(中文版)读书笔记
JavaScript Promise迷你书(中文版)
promise chain
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function taskA() { console.log("Task A"); } function taskB() { console.log("Task B"); } function onRejected(error) { console.log("Catch Error: A or B", error); } function finalTask() { console.log("Final Task"); }
var promise = Promise.resolve(); promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask);
|
上面代码中的promise chain的执行流程,如果用一张图来描述一下的话,像下面的图那样。

Figure 3. promise-then-catch-flow.js附图
在 上述代码 中,我们没有为 then 方法指定第二个参数(onRejected),也可以像下面这样来理解。
then
注册onFulfilled时的回调函数
catch
注册onRejected时的回调函数
再看一下 上面的流程图 的话,我们会发现 Task A 和 Task B 都有指向 onRejected 的线出来。
这些线的意思是在 Task A 或 Task B 的处理中,在下面的情况下就会调用 onRejected 方法。
发生异常的时候
返回了一个Rejected状态的promise对象
在 第一章 中我们已经看到,Promise中的处理习惯上都会采用 try-catch 的风格,当发生异常的时候,会被 catch 捕获并被由在此函数注册的回调函数进行错误处理。
另一种异常处理策略是通过 返回一个Rejected状态的promise对象 来实现的,这种方法不通过使用 throw 就能在promise chain中对 onRejected 进行调用。
关于这种方法由于和本小节关系不大就不在这里详述了,大家可以参考一下第4章 使用reject而不是throw 中的内容。
此外在promise chain中,由于在 onRejected 和 Final Task 后面没有 catch 处理了,因此在这两个Task中如果出现异常的话将不会被捕获,这点需要注意一下。
下面我们再来看一个具体的关于 Task A → onRejected 的例子。
Task A产生异常的例子
Task A 处理中发生异常的话,会按照TaskA → onRejected → FinalTask 这个流程来进行处理。

Figure 4. Task A产生异常时的示意图
将上面流程写成代码的话如下所示。
promise-then-taska-throw.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function taskA() { console.log("Task A"); throw new Error("throw Error @ Task A") } function taskB() { console.log("Task B"); } function onRejected(error) { console.log(error); } function finalTask() { console.log("Final Task"); }
var promise = Promise.resolve(); promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask);
|
执行这段代码我们会发现 Task B 是不会被调用的。
在本例中我们在taskA中使用了 throw 方法故意制造了一个异常。但在实际中想主动进行onRejected调用的时候,应该返回一个Rejected状态的promise对象。关于这种两种方法的异同,请参考 使用reject而不是throw 中的讲解。
promise和操作方法(通过超时取消XHR操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| "use strict"; var requestMap = {}; function createXHRPromise(URL) { var req = new XMLHttpRequest(); var promise = new Promise(function (resolve, reject) { req.open('GET', URL, true); req.onreadystatechange = function () { if (req.readyState === XMLHttpRequest.DONE) { delete requestMap[URL]; } }; req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(new Error(req.statusText)); } }; req.onerror = function () { reject(new Error(req.statusText)); }; req.onabort = function () { reject(new Error('abort this req')); }; req.send(); }); requestMap[URL] = { promise: promise, request: req }; return promise; }
function abortPromise(promise) { if (typeof promise === "undefined") { return; } var request; Object.keys(requestMap).some(function (URL) { if (requestMap[URL].promise === promise) { request = requestMap[URL].request; return true; } }); if (request != null && request.readyState !== XMLHttpRequest.UNSENT) { request.abort(); } } module.exports.createXHRPromise = createXHRPromise; module.exports.abortPromise = abortPromise;
|
定义进行顺序处理的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| function sequenceTasks(tasks) { function recordValue(results, value) { results.push(value); return results; } var pushValue = recordValue.bind(null, []); return tasks.reduce(function (promise, task) { return promise.then(task).then(pushValue); }, Promise.resolve()); } function getURL(URL) { return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(new Error(req.statusText)); } }; req.onerror = function () { reject(new Error(req.statusText)); }; req.send(); }); } var request = { comment: function getComment() { return getURL('http://azu.github.io/promises-book/json/comment.json').then(JSON.parse); }, people: function getPeople() { return getURL('http://azu.github.io/promises-book/json/people.json').then(JSON.parse); } }; function main() { return sequenceTasks([request.comment, request.people]); }
main().then(function (value) { console.log(value); }).catch(function(error){ console.error(error); });
|