简要介绍:Promise允许我们通过链式调用的方式来解决“回调地狱”的问题,特别是在异步过程中,通过Promise可以保证代码的整洁性和可读性。
本文主要介绍一下Promise/A+规范,并在此规范的基础上,自己实现一个Promise。
一、Promise的使用
在了解Promise规范之前,我们知道主流的高版本浏览器已经支持ECMA中的Promise.
创建一个promise实例:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success");
}, 3000);
console.log("this is a promise");
});
p1.then(value => {
console.log(value);
});
// 输出:
// 立马打印:this is a promise
// 延迟3000ms后打印:success
上述是一个promise的实例,输出内容为,“this is a promise”,延迟3000ms后,输出"success"。
从上述的例子可以看出,promise方便处理异步操作。此外promise还可以链式的调用:
let p2 = new Promise((resolve, reject) => {
resolve();
});
p2.then(...).then(...).then(...);
此外Promise除了then方法外,还提供了Promise.resolve、Promise.all、Promise.race等等方法。
二、Promise/A+规范
Promise/A+规范大致有以下内容:
1.术语
(1)"promise"是一个对象或者函数,该对象或者函数有一个then方法
(2)"thenable"是一个对象或者函数,用来定义then方法
(3)"value"是promise状态成功时的值
(4)"reason"是promise状态失败时的值
我们明确术语的目的,是为了在自己实现promise时,保持代码的规范性
2.要求
(1)一个promise必须有3个状态,pending,fulfilled(resolved),rejected。
当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,就不可变。
promise英文译为承诺,也就是说promise的状态一旦发生改变,就永远是不可逆的。
(2)一个promise必须有一个then方法,then方法接受两个参数:
promise1.then(onFulfilled, onRejected);
其中onFulfilled方法表示状态从pending —> fulfilled(resolved)时所执行的方法,而onRejected表示状态从pending —> rejected所执行的方法。
(3)为了实现链式调用,then方法必须返回一个promise
promise2 = promise1.then(onFulfilled, onRejected);
三、实现一个符合Promise/A+规范的Promise
了解了Promise/A+规范之后,下面我们来看如何实现一个Promise。
首先构造一个myPromise函数,关于所有变量和函数名,应该与规范中保持相同。
1.v1.0 初始版本myPromise
function myPromise(constructor) {
let self = this;
self.status = 'pending';
self.value = undefined; // 成功时的值
self.reason = undefined; // 失败时的值
function resolve (value) {
// 1.确保状态只能由 pending 改为 resolved
if (self.status === 'pending') {
self.value = value;
self.status = 'resolved';
}
}
function reject (reason) {
// 2.确保状态只能由 pending 改为 rejected
if (self.status === 'pending') {
self.reason = reason;
self.status = 'rejected';
}
}
try {
constructor(resolve, reject);
} catch(e) {
reject(e);
}
}
同时,需要在myPromise的原型上定义链式调用的then方法:
myPromise.prototype.then = function (onFullfilled, onRejected) {
let self = this;
switch (self.status) {
case 'resolved':
onFullfilled(self.value);
break;
case 'rejected':
onRejected(self.reason);
break;
}
};
上述就是一个初始版本的myPromise,在myPromise里发生状态改变,然后在相应的then方法里面根据不同的状态可以执行不同的操作。
let mp = new myPromise(function (resolve, reject) {
resolve(1);
// reject('err msg');
});
mp.then(function (res) {
console.log(res);
}, function (err) {
console.log(err);
});
// 输出 1
但是这里myPromise无法处理异步的resolve。比如:
let mp1 = new myPromise(function (resolve, reject) {
setTimeout(() => {
resolve(2);
}, 2000);
});
mp1.then(function (res) {
console.log(res);
});
// 无输出
2.v2.0基于观察模式实现
...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。