Promise是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了
1、链式调用
连续执行两个或者多个异步操作是一个常见的需求,在上一个操作执行成功之后,开始下一个的操作,并带着上一步操作所返回的结果。
const promise2 = doSomething().then(successCallback, failureCallback);
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
Catch 的后续链式操作
有可能会在一个回调失败之后继续使用链式操作,即 使用一个 catch
,这对于在链式操作中抛出一个失败之后,再次进行新的操作很有用。
new Promise((resolve, reject) => {
console.log('初始化');
resolve();
})
.then(() => {
throw new Error('有哪里不对了');
console.log('执行「这个」”');
})
.catch(() => {
console.log('执行「那个」');
})
.then(() => {
console.log('执行「这个」,无论前面发生了什么');
});
//执行结果
初始化
执行“那个”
执行“这个”,无论前面发生了什么
2、Promise 拒绝事件
当 Promise 被拒绝时,会有下文所述的两个事件之一被派发到全局作用域(通常而言,就是window
;如果是在 web worker 中使用的话,就是 Worker
或者其他 worker-based 接口)。这两个事件如下所示:
当 Promise 被拒绝、并且在 reject
函数处理该 rejection 之后会派发此事件。
当 Promise 被拒绝,但没有提供 reject
函数来处理该 rejection 时,会派发此事件。
以上两种情况中,PromiseRejectionEvent
事件都有两个属性,一个是 promise
属性,该属性指向被驳回的 Promise,另一个是 reason
属性,该属性用来说明 Promise 被驳回的原因。
3、时序
js是单线程语言,有同步任务和异步任务,异步任务分为宏任务和微任务,promise属于异步微任务。
来两个例子:第二个
Promise.resolve().then(() => console.log(2));
console.log(1); // 1, 2
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait().then(() => console.log(4));
Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
console.log(1); // 1, 2, 3, 4
在旧式回调 API 中创建 Promise
可以通过 Promise 的构造器从零开始创建 Promise
。 这种方式(通过构造器的方式)应当只在包裹旧 API 的时候用到。
setTimeout(() => saySomething("10 seconds passed"), 10000);
混用旧式回调和 Promise 可能会造成运行时序问题。如果 saySomething
函数失败了,或者包含了编程错误,那就没有办法捕获它了。这得怪 setTimeout
。
我们可以用 Promise 来包裹它。最好的做法是,将这些有问题的函数包装起来,留在底层,并且永远不要再直接调用它们:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);
4、嵌套
简便的 Promise 链式编程最好保持扁平化,不要嵌套 Promise,因为嵌套经常会是粗心导致的
嵌套 Promise 是一种可以限制 catch
语句的作用域的控制结构写法。明确来说,嵌套的 catch
仅捕捉在其之前同时还必须是其作用域的 failureres,而捕捉不到在其链式以外或者其嵌套域以外的 error。如果使用正确,那么可以实现高精度的错误修复。
doSomethingCritical()
.then(result => doSomethingOptional()
.then(optionalResult => doSomethingExtraNice(optionalResult))
.catch(e => {console.log(e.message)})) // 即使有异常也会忽略,继续运行;(最后会输出)
.then(() => moreCriticalStuff())
.catch(e => console.log("Critical failure: " + e.message));// 没有输出
参考链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises