前言
Promise 这个东西有两层含义:一个是来自社区的 PromiseA+ 规范,另一个是 ES6 中的 Promise。虽然两者有联系,但也有一些区别。
PromiseA+ 规范
PromiseA+ 规范是一个由开发者社区提出的标准,目的是解决当时 JavaScript 异步操作中的一些问题,如“回调地狱”和缺乏一致的异步处理方式。它为如何实现一个标准的 Promise 提供了详细的指导。简单来说,PromiseA+ 规范是异步编程的一套协议,它规定了 Promise 对象必须具有的行为和功能。
在这个规范中,Promise 是一个“带有 then
方法的东西”。这个“东西”可以是对象,也可以是函数。关键是它必须具备 then
方法,这个方法能够接受两个参数,一个用于处理成功的回调,另一个用于处理失败的回调。
// 符合 Promise A+ 规范的结构
{
then(onFulfilled, onRejected) {
// 实现细节
}
then(onFulfilled, onRejected) {
// ....
}
}
function A() {}
A.then = function(onFulfilled, onRejected) {
// 实现细节
}
A.then .....
A.then .....
then
方法是 PromiseA+ 规范的核心。它负责处理异步操作完成后的逻辑,并返回一个新的 Promise,使得 Promise 可以链式调用。这种设计使得我们能够避免嵌套的回调,从而解决了“回调地狱”问题。
ES6 的 Promise
在 ES6 规范中,加入了原生的 Promise 支持。通过一个构造函数 Promise 去做一些事情。通过构造函数创建出来的实例,满足了PromiseA+规范。也可以称之为 PromiseA+ 规范的实现。
简单粗暴地理解为:PromiseA+ 社区提供了一个蓝本,一份草稿,然后 ES6 的Promise构造函数就将这份规范给实现了。
所以,我们可以看到,只要我们 new 了一个 Promise,那么这个实例化对象就带有 then
方法。
const _promise = new Promise((res, rej) => console.log(res));
// 这里实例化后的 _promise 带有原型链上的 then 方法
_promise.then;
除此之外,ES6 对 PromiseA+ 规范进行了扩展,除了 then
方法外,还有 catch
和 finally
等。
catch
方法:catch
用来捕获 Promise 中的错误。它是 then
的一个简化版,用来处理失败的情况。
var p = new Promise((resolve, reject) => {
// 这里是一些异步操作
reject("出错了"); // 比如说操作失败了
});
p.catch(error => {
console.log(error); // 这里会输出 "出错了"
});
finally
方法:finally
是无论 Promise 成功还是失败,都会执行的一段代码。它通常用来做一些清理工作,比如关闭网络连接、隐藏加载动画等。
p.finally(() => {
console.log("操作结束,无论成功或失败都会执行");
});
Promise.all()
:Promise.all()
接受一个 Promise 数组,当所有的 Promise 都成功时,返回一个新的 Promise,这个 Promise 的值是所有 Promise 结果的数组。如果有一个 Promise 失败,那么返回的 Promise 也会立即失败。
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log(results); // 输出所有 Promise 的结果
})
.catch(error => {
console.error(error); // 输出第一个失败的原因
});
Promise.race()
:Promise.race()
也是接受一个 Promise 数组,只不过它是哪个 Promise 先完成就返回哪个的结果。如果第一个完成的是失败的,那么整个 Promise.race()
就失败。
Promise.race([promise1, promise2, promise3])
.then(result => {
console.log(result); // 输出第一个完成的 Promise 结果
})
.catch(error => {
console.error(error); // 输出第一个失败的原因
});