一、Promise的声明
首先呢,Promise
肯定是一个类,我们就用class
来声明。
• 由于 new Promise((resolve, reject)=>{})
,所以传入一个参数(函数),PromiseA+
里叫他executor
(作业执行器),传入就执行。
•executor
里面有两个参数,一个叫resolve
(成功),一个叫reject
(失败)。
•由于resolve
和reject
可执行,所以都是函数,我们用let
声明。
class Promise {
// 构造器
constructor(executor) {
// 成功
let resolve = () => {};
// 失败
let reject = () => {};
// 立即执行
executor(resolve, reject);
}
}
二、解决基本状态
PromiseA+
对Promise
有规定:
Promise
存在三个状态(state
)pending
、fulfilled
、rejected
pending
(等待态)为初始态,并可以转化为fulfilled
(成功态)和rejected
(失败态)- 成功时,不可转为其他状态,且必须有一个不可改变的值(
value
) - 失败时,不可转为其他状态,且必须有一个不可改变的原因(
reason
) new Promise((resolve, reject)=>{resolve(value)})
resolve
为成功,接收参数value
,状态改变为fulfilled
,不可再次改变。new Promise((resolve, reject)=>{reject(reason)})
reject
为失败,接收参数reason
,状态改变为rejected
,不可再次改变。- 若是
executor
函数报错 直接执行reject()
;
于是乎,我们获得以下代码:
class Promise {
// 构造器
constructor(executor) {
// 初始化state为等待态
this.state = 'pending'
// 成功的值
this.value = undefined
// 失败的原因
this.reason = undefined
// 成功
let resolve = value => {
// state改变,resolve调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled'
// 储存成功的值
this.value = value
}
}
// 失败
let reject = reason => {
// state改变,reject调用就会失败
if (this.state === 'pending') {
// reject调用后,state转化为失败态
this.state = 'rejected'
// 储存失败的原因
this.reason = reason
}
}
// 如果executor执行报错,直接执行reject
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
}
三、then方法
PromiseA+
规定:Promise
有一个叫做then
的方法,里面有两个参数:onFulfilled
,onRejected
,成功有成功的值,失败有失败的原因
•当状态state
为fulfilled
,则执行onFulfilled
,传入this.value
。当状态state
为rejected
,则执行onRejected
,传入this.value
•onFulfilled
,onRejected
如果他们是函数,则必须分别在fulfilled
,rejected
后被调用,value
或reason
依分别为他们的第一个参数
class Promise {
// 构造器
constructor(executor) {...}
// then方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.state === 'fulfilled') {
onFulfilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
}
}
四、解决异步实现
现在基本可以实现简单的同步代码,但是当resolve
在setTomeout
内执行,then
时state
还是pending
等待状态 我们就需要在then
调用的时候,将成功和失败存到各自的数组,一旦reject
或者resolve
,就调用它们
类似于发布订阅,先将then
里面的两个函数储存起来,由于一个Promise
可以有多个then
,所以存在同一个数组内。
// 多个then的情况
let p = new Promise();
p.then();
p.then();
成功或者失败时,forEach
调用它们
class Promise {
// 构造器
constructor(executor) {
// 初始化state为等待态
this.state = 'pending'
// 成功的值
this.value = undefined
// 失败的原因
this.reason = undefined
/* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
// 成功存放的数组
this.onResolvedCallbacks = []
// 失败存放的数组
this.onRejectedCallbacks = []
/* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */
// 成功
let resolve = value => {
// state改变,resolve调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled'
// 储存成功的值
this.value = value
/* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn=>fn())
/* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */
}
}
// 失败
let reject = reason => {
// state改变,reject调用就会失败
if (this.state === 'pending') {
// reject调用后,state转化为失败态
this.state = 'rejected'
// 储存失败的原因
this.reason = reason
/* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach(fn=>fn())
/* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */
}
}
// 如果executor执行报错,直接执行reject
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
// then方法 有两个参数 onFulfilled onRejected
then(onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.state === 'fulfilled') {
onFulfilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
/* ↓↓↓↓↓↓↓↓↓↓新加的代码↓↓↓↓↓↓↓↓↓↓ */
// 当状态为pending时
if(this.state ==='pending'){
// onFullfilled传入到成功数组
this.onRejectedCallbacks.push(()=>{
onFullfilled(this.value)
})
// onRejected传入到失败数组
this.onRejectedCallbacks.push(()=>{
onRejected(this.reason) // 原文中这里写的是value,我认为是reason
})
}
/* ↑↑↑↑↑↑↑↑↑↑新加的代码↑↑↑↑↑↑↑↑↑↑ */
}
}
五、解决链式调用
我们常常用到 new Promise().then().then()
,这就是链式调用,用来解决回调地狱
1、为了达成链式,我们默认在第一个then
里返回一个promise
。PromiseA+
规定了一种方法,就是在then
里面返回一个新的promise
,称为promise2
: promise2 = new Promise((resolve, reject)=>{})
•将这个promise2
返回的值传递到下一个then
中
•如果返回一个普通的值,则将普通的值传递给下一个then
中
2、当我们在第一个then
中 return
了一个参数(参数未知,需判断)。这个return
出来的新的promise
就是onFulfilled()
或onRejected()
的值
PromiseA+
则规定onFulfilled()
或onRejected()
的值,即第一个then
返回的值,叫做x
,判断x
的函数叫做resolvePromise
class Promise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
let reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// 声明返回的promise2
let promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
};
if (this.state === 'rejected') {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
};
if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
})
this.onRejectedCallbacks.push(() => {
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
})
}
});
// 返回promise2,完成链式
return promise2;
}
}
完成resolvePromise函数以及更多实现参考原文:
https://www.cnblogs.com/sugar-tomato/p/11353546.html