Promise/A+
下面是一个简单的Promise的实例
const promise1 = new Promise((resolve, reject) => {
console.log(1);
resolve(2);
console.log(3);
reject(4);
});
const promise2 = new Promise((resolve, reject) => {
reject(5);
});
console.log(6);
promise1.then(console.log, console.log);
promise2.then(console.log, console.log);
它对应的输出结果为
1
3
6
2
5
结合Promise/A+规范,可以总结出Promise基本特征如下所示(promise表示Promise的实例)
new Promise时,需要传入一个立即执行函数executorexecutor接受两个异步执行的回调函数,分别是成功后的回调resolve和失败后的回调rejectpromise只有三个状态,pending,fulfilled,rejectedpromise初始状态为pendingpromise只能从pending修改为fulfilled或者rejected,修改以后不可逆,无法再次修改promise有一个value属性,用来保存成功后返回的值promise有一个reason属性,用来保存失败后返回的值promise有一个then方法,接收Promise成功的回调onFulfilled和Promise失败的回调onRejected
Promise 基本结构
下面是一个 Promise 的基本结构
const PromiseStatusEnum = {
PENDING: 'pending',
FULFILLED: 'fulfilled',
REJECTED: 'rejected'
};
class MyPromise {
constructor(executor) {
this.status = PromiseStatusEnum.PENDING;
this.value = null;
this.reason = null;
this.resolveQueue = [];
this.rejectQueue = [];
}
then = (onFulfilled, onRejected) => {};
catch = (onRejected) => {};
finally = (callback) => {};
static resolve = (value) => {};
static reject = (error) => {};
static all = (promiseArr) => {};
static race = (promiseArr) => {};
}
executor
executor接受两个回调函数resolve和reject,通过箭头函数绑定当前实例的this,通过setTimeout异步执行
const resolve = (value) => {
const run = () => {};
setTimeout(run);
};
const reject = (error) => {
const run = () => {};
setTimeout(run);
};
run主要负责
- 判断当前的状态是否为
pending,并对其修改 - 记录成功或者失败的返回值
基本的executor如下
const resolve = (value) => {
const run = () => {
if (this.status === PromiseStatusEnum.PENDING) {
this.status = PromiseStatusEnum.FULFILLED;
this.value = value;
}
};
setTimeout(run);
};
const reject = (error) => {
const run = () => {
if (this.status === PromiseStatusEnum.PENDING) {
this.status = PromiseStatusEnum.REJECTED;
this.reason = error;
}
};
setTimeout(run);
};
//兼容executor的异常情况
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
then
then接受两个回调函数onFulfilled和onRejected,并返回一个Promise对象
then = (onFulfilled, onRejected) => {
// onFulfilled或者onRejected不是函数时,返回当前的值
typeof onFulfilled !== 'function' ? (onFulfilled = (value) => value) : null;
typeof onRejected !== 'function' ? (onRejected = (error) => error) : null;
return new MyPromise((resolve, reject) => {});
};
再根据promise的状态进行不同的操作
- 当
state === 'fulfilled'时,执行 onFulfilled - 当
state === 'rejected'时,执行 onRejected - 如果在执行回调函数时抛出了异常,那么就会把这个异常作为参数,直接
reject - 回调函数返回的值不是
Promise,直接resolve - 回调函数返回的值是
Promise,调用then方法,保证Promise会被全部执行 - 当
state === 'pending'时,需要将回调函数放入队列中,等待执行
then = (onFulfilled, onRejected) => {
return new MyPromise((resolve, reject) => {
const resolveFn = (value) => {
try {
const x = onFulfilled(value);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
};
const rejectFn = (error) => {
try {
const x = onRejected(error);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
};
switch (this.status) {
case PromiseStatusEnum.PENDING:
this.resolveQueue.push(resolveFn);
this.rejectQueue.push(rejectFn);
break;
case PromiseStatusEnum.FULFILLED:
resolveFn(this.value);
break;
case PromiseStatusEnum.REJECTED:
rejectFn(this.reason);
break;
}
});
};
resolveQueue和rejectQueue收集的回调,需要在executor中的resolve和reject执行
const resolve = (value) => {
const run = () => {
if (this.status === PromiseStatusEnum.PENDING) {
this.status = PromiseStatusEnum.FULFILLED;
this.value = value;
while (this.resolveQueue.length) {
const callback = this.resolveQueue.shift();
callback(value);
}
}
};
setTimeout(run);
};
const reject = (error) => {
const run = () => {
if (this.status === PromiseStatusEnum.PENDING) {
this.status = PromiseStatusEnum.REJECTED;
this.reason = error;
while (this.rejectQueue.length) {
const callback = this.rejectQueue.shift();
callback(error);
}
}
};
setTimeout(run);
};
catch
实现了then以后,catch就比较简单了,直接调用then,onFulfilled传空就行了
catch = (onRejected) => this.then(undefined, onRejected);
finally
finally接受一个回调函数,在promise结束时,无论结果是fulfilled或者是rejected,都会执行该回调函数
finally = (callback) =>
this.then(
(value) => MyPromise.resolve(callback()).then(() => value),
(error) => MyPromise.resolve(callback()).then(() => MyPromise.reject(error))
);
完整代码
还有一些静态方法,resolve,reject,all,reace等,基本实现了Promise以后,就比较简单了,不在赘述了
const PromiseStatusEnum = {
PENDING: 'pending',
FULFILLED: 'fulfilled',
REJECTED: 'rejected'
};
class MyPromise {
constructor(executor) {
this.status = PromiseStatusEnum.PENDING;
this.value = null;
this.reason = null;
this.resolveQueue = [];
this.rejectQueue = [];
const resolve = (value) => {
const run = () => {
if (this.status === PromiseStatusEnum.PENDING) {
this.status = PromiseStatusEnum.FULFILLED;
this.value = value;
while (this.resolveQueue.length) {
const callback = this.resolveQueue.shift();
callback(value);
}
}
};
setTimeout(run);
};
const reject = (error) => {
const run = () => {
if (this.status === PromiseStatusEnum.PENDING) {
this.status = PromiseStatusEnum.REJECTED;
this.reason = error;
while (this.rejectQueue.length) {
const callback = this.rejectQueue.shift();
callback(error);
}
}
};
setTimeout(run);
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then = (onFulfilled, onRejected) => {
return new MyPromise((resolve, reject) => {
const resolveFn = (value) => {
try {
const x = onFulfilled(value);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
};
const rejectFn = (error) => {
try {
const x = onRejected(error);
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x);
} catch (error) {
reject(error);
}
};
switch (this.status) {
case PromiseStatusEnum.PENDING:
this.resolveQueue.push(resolveFn);
this.rejectQueue.push(rejectFn);
break;
case PromiseStatusEnum.FULFILLED:
resolveFn(this.value);
break;
case PromiseStatusEnum.REJECTED:
rejectFn(this.reason);
break;
}
});
};
catch = (onRejected) => this.then(undefined, onRejected);
finally = (callback) =>
this.then(
(value) => MyPromise.resolve(callback()).then(() => value),
(error) => MyPromise.resolve(callback()).then(() => MyPromise.reject(error))
);
static resolve = (value) =>
new MyPromise((resolve, reject) =>
value instanceof MyPromise ? value : new MyPromise((resolve, reject) => resolve(value))
);
static reject = (error) => new MyPromise((resolve, reject) => reject(error));
// 静态all方法
static all = (promiseArr) => {
let count = 0;
let result = [];
return new MyPromise((resolve, reject) => {
if (!promiseArr.length) {
return resolve(result);
}
promiseArr.forEach((p, i) => {
MyPromise.resolve(p).then(
(value) => {
count++;
result[i] = value;
if (count === promiseArr.length) {
resolve(result);
}
},
(error) => {
reject(error);
}
);
});
});
};
// 静态race方法
static race = (promiseArr) =>
new MyPromise((resolve, reject) => {
promiseArr.forEach((p) => {
MyPromise.resolve(p).then(
(value) => {
resolve(value);
},
(error) => {
reject(error);
}
);
});
});
}
const promise1 = new MyPromise((resolve, reject) => {
console.log(1);
resolve(2);
console.log(3);
reject(4);
});
const promise2 = new MyPromise((resolve, reject) => {
reject(5);
});
console.log(6);
promise1.then(console.log, console.log);
promise2.then(console.log, console.log);
它对应的输出结果与之前一致
1
3
6
2
5