本文侧重侧重讲解Promise的原理,如果对Promise使用不太熟的小伙伴可参考阮一峰老师的文章ECMAScript 6 入门。
Promise有三种状态,分别是pending、fulfilled和reject,一旦改变便不会再更改。
所以第一步,我们把这个功能先实现。
export default class MyPromise {
constructor(handle) {
this['[[PromiseState]]'] = "pending" //Promise的状态
this['[[PromiseResult]]'] = undefined; //Promise的值
handle(this._resolve,this._reject)
}
_resolve = (val) => {
//1.修改Promise的状态 2.修改Promise的值
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val;
}
}
_reject = (err) => {
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "rejected";
this['[[PromiseResult]]'] = err;
}
}
}
第二步 实现then方法,then方法可以接受两个回调函数作为参数。这个两个回调函数接受Promise的值作为参数。
export default class MyPromise {
constructor(handle) {
this['[[PromiseState]]'] = "pending" //promise的状态
this['[[PromiseResult]]'] = undefined; //promise的值
this.resolveFn = undefined;
this.rejectFn = undefined;
handle(this._resolve,this._reject)
}
_resolve = (val) => {
//1.修改promise的状态 2.修改promise的值
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val;
setTimeout(()=>{
this.resolveFn(val)
})
}
}
_reject = (err) => {
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "rejected";
this['[[PromiseResult]]'] = err;
setTimeout(()=>{
this.rejectFn(err)
})
}
}
then(onResolved,onRejected){
this.resolveFn = onResolved;
this.rejectFn = onRejected;
}
}
写到此处then有4个问题还没解决 。
1.多个then的问题(不是链式调用)
即如下面这样多次调用then。
const p1 = new Promise((res)=>{
setTimeout(()=>{
res(1)
})
})
p1.then((value)=>{
console.log(value + 1) // 2
})
p1.then((value)=>{
console.log(value + 2) // 3
})
2、then的同步执行顺序问题(微任务、宏任务)。
3、then的链式调用。
第三步解决多个then的调用问题。将then接受的回调函数用数组收集起来,解决多个then的调用问题。
export default class MyPromise {
constructor(handle) {
this['[[PromiseState]]'] = "pending" //promise的状态
this['[[PromiseResult]]'] = undefined; //promise的值
this.onResolvedCallback = [] // Promise resolve时的回调函数集
this.onRejectedCallback = [] // Promise reject时的回调函数集
// this.resolveFn = undefined;
// this.rejectFn = undefined;
handle(this._resolve,this._reject)
}
_resolve = (val) => {
//1.修改promise的状态 2.修改promise的值
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val;
setTimeout(()=>{
let cb;
while(cb = this.onResolvedCallback.shift()) {
typeof cb ==='function' && cb(val);
}
})
}
}
_reject = (err) => {
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "rejected";
this['[[PromiseResult]]'] = err;
setTimeout(()=>{
let cb;
while(cb = this.onRejectedCallback.shift()) {
typeof cb ==='function' && cb(err);
}
})
}
}
then(onResolved,onRejected){
this.onResolvedCallback.push(onResolved);
this.onRejectedCallback.push(onRejected);
}
}
第四步、then的同步执行顺序问题。then里面的回调函数属于微任务,当前所有同步代码执行完毕然后执行then里面的回调函数,再执行定时器这些宏任务。
const my = new MyPromise((res)=>{
console.log('Promise')
setTimeout(()=>{
console.log(1)
})
res(2);
});
my.then((value)=>{
console.log(value)
});
/*打印的顺序为promise、1、2,这个顺序是不对的。
上述代码中,正确的执行顺序应该是,MyPromise新建后立即执行,首先输出Promise,然后输出2,最后输出1。
为了让then收集的回调函数执行的时候有微任务的效果,可以用MutationObserver模拟一下,MutationObserver的具体用法可以参照MDN。
export default class MyPromise {
constructor(handle) {
this['[[PromiseState]]'] = "pending" //promise的状态
this['[[PromiseResult]]'] = undefined; //promise的值
this.onResolvedCallback = [] // Promise resolve时的回调函数集
this.onRejectedCallback = [] // Promise reject时的回调函数集
// this.resolveFn = undefined;
// this.rejectFn = undefined;
handle(this._resolve,this._reject)
}
_resolve = (val) => {
//1.修改promise的状态 2.修改promise的值
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "fulfilled"
this['[[PromiseResult]]'] = val;
const executor = () => {
let cb;
while(cb = this.onResolvedCallback.shift()) {
typeof cb ==='function' && cb(val);
}
}
const obj = new MutationObserver(executor);
obj.observe(document.body,{
attributes:true
});
document.body.setAttribute("Promise","MyPromise")
// setTimeout(()=>{
// let cb;
// while(cb = this.onResolvedCallback.shift()) {
// typeof cb ==='function' && cb(val);
// }
// })
}
}
_reject = (err) => {
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "rejected";
this['[[PromiseResult]]'] = err;
// setTimeout(()=>{
// let cb;
// while(cb = this.onRejectedCallback.shift()) {
// typeof cb ==='function' && cb(err);
// }
// })
const executor = () => {
let cb;
while(cb = this.onRejectedCallback.shift()) {
typeof cb ==='function' && cb(val);
}
}
const obj = new MutationObserver(executor);
obj.observe(document.body,{
attributes:true
});
document.body.setAttribute("Promise","MyPromise")
}
}
then(onResolved,onRejected){
this.onResolvedCallback.push(onResolved);
this.onRejectedCallback.push(onRejected);
}
}
第五步、解决then的链式调用的问题。then调用后会返回一个新的Promise实例。
export default class MyPromise {
constructor(handle) {
this['[[PromiseState]]'] = "pending" //promise的状态
this['[[PromiseResult]]'] = undefined; //promise的值
this.onResolvedCallback = [] // Promise resolve时的回调函数集
this.onRejectedCallback = [] // Promise reject时的回调函数集
// this.resolveFn = undefined;
// this.rejectFn = undefined;
handle(this._resolve, this._reject)
}
_resolve = (val) => {
//1.修改promise的状态 2.修改promise的值
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "fulfilled";
this['[[PromiseResult]]'] = val;
const executor = () => {
let cb;
while (cb = this.onResolvedCallback.shift()) {
cb && cb(val);
}
}
const obj = new MutationObserver(executor);
obj.observe(document.body, {
attributes: true
});
document.body.setAttribute("Promise", "MyPromise")
// setTimeout(()=>{
// let cb;
// while(cb = this.onResolvedCallback.shift()) {
// typeof cb ==='function' && cb(val);
// }
// })
}
}
_reject = (err) => {
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "rejected";
this['[[PromiseResult]]'] = err;
// setTimeout(()=>{
// let cb;
// while(cb = this.onRejectedCallback.shift()) {
// typeof cb ==='function' && cb(err);
// }
// })
const executor = () => {
let cb;
while (cb = this.onRejectedCallback.shift()) {
cb && cb(val);
}
}
const obj = new MutationObserver(executor);
obj.observe(document.body, {
attributes: true
});
document.body.setAttribute("Promise", "MyPromise")
}
}
then(onResolved, onRejected) {
return new MyPromise((resolve,reject) => {
const resloveFn = (val) => {
const res = typeof onResolved === 'function' && onResolved(val);
//如果then里面的回调函数返回的是一个Promise实例
if (res instanceof MyPromise) {
res.then((result) => {
resolve(result)
})
} else {
console.log(res,'执行的结果')
resolve(res)
}
}
this.onResolvedCallback.push(resloveFn);
const rejectFn = (err) => {
typeof onRejected === 'function' && onRejected(err);
reject(err);
}
this.onRejectedCallback.push(rejectFn);
})
}
}
第六步、Promise的一些其他静态方法
export default class MyPromise {
constructor(handle) {
this['[[PromiseState]]'] = "pending";//promise的状态
this['[[PromiseResult]]'] = undefined; //promise的值
this.onResolvedCallback = [];// Promise resolve时的回调函数集
this.onRejectedCallback = [];// Promise reject时的回调函数集
// this.resolveFn = undefined;
// this.rejectFn = undefined;
handle(this._resolve, this._reject);
}
_resolve = (val) => {
//1.修改promise的状态 2.修改promise的值
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "fulfilled";
this['[[PromiseResult]]'] = val;
const executor = () => {
let cb;
while (cb = this.onResolvedCallback.shift()) {
cb && cb(val);
}
}
const obj = new MutationObserver(executor);
obj.observe(document.body, {
attributes: true
});
document.body.setAttribute("Promise", "MyPromise");
// setTimeout(()=>{
// let cb;
// while(cb = this.onResolvedCallback.shift()) {
// typeof cb ==='function' && cb(val);
// }
// })
}
}
_reject = (err) => {
if (this['[[PromiseState]]'] === "pending") {
this['[[PromiseState]]'] = "rejected";
this['[[PromiseResult]]'] = err;
// setTimeout(()=>{
// let cb;
// while(cb = this.onRejectedCallback.shift()) {
// typeof cb ==='function' && cb(err);
// }
// })
const executor = () => {
let cb;
while (cb = this.onRejectedCallback.shift()) {
cb && cb(err);
}
}
const obj = new MutationObserver(executor);
obj.observe(document.body, {
attributes: true
});
document.body.setAttribute("Promise", "MyPromise");
}
}
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
const resloveFn = (val) => {
const res = typeof onResolved === 'function' && onResolved(val);
//如果then里面的回调函数返回的是一个Promise实例
if (res instanceof MyPromise) {
res.then((result) => {
resolve(result);
})
} else {
resolve(res);
}
}
this.onResolvedCallback.push(resloveFn);
const rejectFn = (err) => {
typeof onRejected === 'function' && onRejected(err);
reject(err);
}
this.onRejectedCallback.push(rejectFn);
})
}
static resolve(value) {
return new MyPromise(resolve => {
resolve(value);
})
}
static reject(err) {
return new MyPromise((resolve, reject) => {
reject(err);
})
}
static race(arr) {
return new MyPromise((resolve, reject) => {
arr.forEach((promise) => {
promise.then((value) => {
resolve(value);
}, (error) => {
reject(error);
})
})
})
}
static all(promises) {
return new MyPromise((resolve) => {
const result = [];
let index = 0;
let len = promises.length;
if (len === 0) {
resolve(result);
return;
}
for (let i = 0; i < len; i++) {
promises[i].then((res) => {
result[i] = res;
index++;
if (index === len) {
resolve(result);
}
})
}
})
}
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
const result = [];
let index = 0;
let len = promises.length;
if (len === 0) {
resolve(result);
}
for(let i = 0; i < len; i++){
const obj = {};
promises[i].then((val)=>{
obj.status = "fulfilled";
obj.value = val;
result[i] = obj;
index++;
if (index === len) {
resolve(result);
}
},(err)=>{
obj.status = "rejected";
obj.reason = err;
result[i] = obj;
index++;
if (index === len) {
resolve(result);
}
})
}
})
}
}
本文虽然有一些细节的地方没考虑周全,达不到Promise/A+的标准,但基本雏形都在适合第一次手写Promise的小伙伴入个门。