手写Promise源码的实现思路
Promise
的使用:
let promise = new Promise((resolve, reject) => {
resolve("OK");
// reject("Error");
});
console.log(promise);
promise.then(value => {
console.log("success");
}, error => {
console.log("fail");
});
-
定义构造函数中的两个基本属性
PromiseState
,PromiseResult
function Promise() { this.PromiseState = "pending"; this.PromiseResult = null; }
-
由于实例对象中传递的参数是一个执行器函数,并且会立即执行这个函数。
function Promise(executor) { this.PromiseState = "pending"; this.PromiseResult = null; executor(); }
-
该执行器函数中有两个函数参数,调用任意一个函数会改变promise的状态和结果值,且状态只能改变一次。
function Promise(executor) { this.PromiseState = "pending"; this.PromiseResult = null; // 防止this指向window const self = this; function resolve(value) { if(self.PromiseState !== "pending") return; self.PromiseState = "fulfilled"; self.PromiseResult = value; } function reject(reason) { if(self.PromiseState !== "pending") return; self.PromiseState = "rejected"; self.PromiseResult = reason; } // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值 executor(resolve, reject); }
-
还有一种情况:promise实例执行结果为抛出异常,需要让其状态为失败。
function Promise(executor) { // ... // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败 try { executor(resolve, reject); } catch (error) { reject(error); } }
-
在对象原型上添加
then
方法。Promise.prototype.then = function(onResolved, onRejected) { if(this.PromiseState === "fulfilled") { onResolved(); } if(this.PromiseState === "rejected") { onRejected(); } }
-
executor
的执行内容是异步的,应该等到异步执行后改变了状态才能执行then
中的回调函数,异步执行前状态还是为pending
。let promise = new Promise((resolve, reject) => { setTimeout(()=> { resolve("OK"); }, 1000); });
function Promise(executor) { // ... this.callback = null; // 防止this指向window const self = this; function resolve(value) { if(self.PromiseState !== "pending") return; self.PromiseState = "fulfilled"; self.PromiseResult = value; if(self.callback.onResolved) { self.callback.onResolved(); } } function reject(reason) { if(self.PromiseState !== "pending") return; self.PromiseState = "rejected"; self.PromiseResult = reason; if(self.callback.onRejected) { self.callback.onRejected(); } } // ... } // then方法 Promise.prototype.then = function(onResolved, onRejected) { // ... if(this.PromiseState === "pending") { // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来 this.callback = { onResolved, onRejected }; } }
-
当一个
Promise
实例执行了多个then
方法时,两个then里的方法都会执行。let promise = new Promise((resolve, reject) => { resolve("OK"); }); promise.then(value => { console.log("success"); }, error => { console.log("fail"); }); promise.then(value => { console.log("success2"); }, error => { console.log("fail2"); }); // success success2
function Promise(executor) { // ... this.callback = null; // 防止this指向window const self = this; function resolve(value) { if(self.PromiseState !== "pending") return; self.PromiseState = "fulfilled"; self.PromiseResult = value; self.callbacks.forEach(item => { item.onResolved(); }); } function reject(reason) { if(self.PromiseState !== "pending") return; self.PromiseState = "rejected"; self.PromiseResult = reason; self.callbacks.forEach(item => { item.onRejected(); }); } // ... } // then方法 Promise.prototype.then = function(onResolved, onRejected) { // ... if(this.PromiseState === "pending") { // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来 this.callbacks.push({ onResolved, onRejected }); } }
-
then
方法返回的也是一个Promise
实例,这个实例的状态由执行的回调函数的结果来决定,如果回调函数的执行内容是非Promise
实例,则都为成功状态;如果是Promise
实例,状态根据这个实例的状态来定。-
executor
执行内容为同步时:Promise.prototype.then = function(onResolved, onRejected) { const self = this; return new Promise((resolve, reject) => { if(self.PromiseState === "fulfilled") { // 拿到回调函数的返回值 // Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功 const result = onResolved(self.PromiseResult); if(result instanceof Promise) { // 既然是一个Promise实例,就能根据该实例的执行内容确定状态 result.then(v => { resolve(v); }, r => { reject(r); }); } else { resolve(result); } } if(self.PromiseState === "rejected") { // 同上 const result = onRejected(self.PromiseResult); if(result instanceof Promise) { result.then(v => { resolve(v); }, r => { reject(r); }); } else { resolve(result); } } } // ... }) }
-
executor
执行内容为异步时:Promise.prototype.then = function(onResolved, onRejected) { const self = this; return new Promise((resolve, reject) => { // ... if(self.PromiseState === "pending") { // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来 self.callbacks.push({ onResolved: function() { // 同上 const result = onResolved(self.PromiseResult); if(result instanceof Promise) { result.then(v => { resolve(v); }, r => { reject(r); }); } else { resolve(result); } }, onRejected: function() { // 同上 const result = onRejected(self.PromiseResult); if(result instanceof Promise) { result.then(v => { resolve(v); }, r => { reject(r); }); } else { resolve(result); } } }); } }) }
-
-
封装
then
方法中出现的重复代码,并处理Promise.prototype.then = function(onResolved, onRejected) { const self = this; return new Promise((resolve, reject) => { // 封装函数:根据结果改变状态 function callback(fn) { try { // 拿到回调函数的返回值 // Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功 let result = fn(self.PromiseResult); if(result instanceof Promise) { // 既然是一个Promise实例,就能根据该实例的执行内容确定状态 result.then(v => { resolve(v); }, r => { reject(r); }); } else { resolve(result); } } catch (error) { reject(error); } } if(self.PromiseState === "fulfilled") { callback(onResolved); } if(self.PromiseState === "rejected") { callback(onRejected); } if(self.PromiseState === "pending") { // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来 self.callbacks.push({ onResolved: function() { callback(onResolved); }, onRejected: function() { callback(onRejected); } }); } }) }
-
添加
catch
方法并实现异常穿透,同时实现then
只传递一个参数和不传递参数的情况。// 使用 promise.then(value => { return new Promise((resolve, reject) => { reject("111 error") }) }).then((value) => { console.log(222) }).catch(err => { console.log("err-------------") console.log(err) });
// then方法 Promise.prototype.then = function(onResolved, onRejected) { const self = this; // 不传第二个函数时,默认函数为一个抛出异常操作 if(typeof onRejected !== "function") { onRejected = reason => { throw reason; } } // 不传第一个函数时,默认将实例结果值返回,可以实现成功时的值传递 if(typeof onResolved !== "function") { onResolved = value => value; } return new Promise((resolve, reject) => { // ... }) } // catch方法 Promise.prototype.catch = function(onRejected) { return this.then(undefined, onRejected); }
-
添加
Promise.resolve
和Promisereject
方法。// resolve方法:根据传入参数的类型决定结果的状态 Promise.resolve = function(value) { return new Promise((resolve, reject) => { if(value instanceof Promise) { // 既然是一个Promise实例,就能根据该实例的执行内容确定状态 value.then(v => { resolve(v); }, r => { reject(r); }); } else { resolve(value); } }) } // reject方法:无论传入的参数是什么类型,结果都是失败状态 Promise.reject = function(reason) { return new Promise((resolve, reject) => { reject(reason); }) }
-
添加
Promise.all
方法:所有实例都成功则为成功,结果值为所有实例结果值组成的数组;有一个失败,则为失败,结果值为失败的实例的结果值。Promise.all = function(promises) { return new Promise((resolve, reject) => { let count = 0, resultArr = []; promises.forEach((item, index) => { item.then(v => { count++; // 按实例的索引值存储其对应结果 resultArr[index] = item.PromiseResult; // 全部都为成功时为成功 if(count === promises.length) { resolve(resultArr); } }, r => { reject(r); }); }); }) }
-
添加
Promise.race
方法:实例中谁先改变状态,返回的状态和结果值就为该实例的状态和结果值。Promise.race = function(promises) { return new Promise((resolve, reject) => { promises.forEach(item => { item.then(v => { resolve(v); }, r => { reject(r); }); }); }) }
-
then
方法是一个异步任务。function Promise(executor) { // ... // 防止this指向window const self = this; function resolve(value) { // ... setTimeout(() => { self.callbacks.forEach(item => { item.onResolved(); }); }); } function reject(reason) { // ... setTimeout(() => { self.callbacks.forEach(item => { item.onRejected(); }); }); } // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败 try { executor(resolve, reject); } catch (error) { reject(error); } } // then方法 Promise.prototype.then = function(onResolved, onRejected) { // ... return new Promise((resolve, reject) => { // ... if(self.PromiseState === "fulfilled") { setTimeout(() => { callback(onResolved); }); } if(self.PromiseState === "rejected") { setTimeout(() => { callback(onRejected); }); } // ... }) }
调整一下代码结构,整个promise.js
源码如下:
function Promise(executor) {
this.PromiseState = "pending";
this.PromiseResult = null;
this.callbacks = [];
// 防止this指向window
const self = this;
function resolve(value) {
if(self.PromiseState !== "pending") return;
self.PromiseState = "fulfilled";
self.PromiseResult = value;
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved();
});
});
}
function reject(reason) {
if(self.PromiseState !== "pending") return;
self.PromiseState = "rejected";
self.PromiseResult = reason;
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected();
});
});
}
// 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then方法
Promise.prototype.then = function(onResolved, onRejected) {
// 不传第一个函数时,默认将实例结果值返回,可以实现成功时的值传递
if(typeof onResolved !== "function") {
onResolved = value => value;
}
// 不传第二个函数时,默认函数为一个抛出异常操作
if(typeof onRejected !== "function") {
onRejected = reason => {
throw reason;
}
}
const self = this;
return new Promise((resolve, reject) => {
// 封装函数:根据结果改变状态
function callback(fn) {
try {
// 拿到回调函数的返回值
// Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功
let result = fn(self.PromiseResult);
if(result instanceof Promise) {
// 既然是一个Promise实例,就能根据该实例的执行内容确定状态
result.then(v => {
resolve(v);
}, r => {
reject(r);
});
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
if(self.PromiseState === "pending") {
// 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来
self.callbacks.push({
onResolved: function() {
callback(onResolved);
},
onRejected: function() {
callback(onRejected);
}
});
} else if(self.PromiseState === "fulfilled") {
setTimeout(() => {
callback(onResolved);
});
} else if(self.PromiseState === "rejected") {
setTimeout(() => {
callback(onRejected);
});
}
})
}
// catch方法
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
}
// resolve方法:根据传入参数的类型决定结果的状态
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
if(value instanceof Promise) {
// 既然是一个Promise实例,就能根据该实例的执行内容确定状态
value.then(v => {
resolve(v);
}, r => {
reject(r);
});
} else {
resolve(value);
}
})
}
// reject方法:无论传入的参数是什么类型,结果都是失败状态
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
// all方法
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
let count = 0,
resultArr = [];
promises.forEach((item, index) => {
item.then(v => {
count++;
// 按实例的索引值存储其对应结果
resultArr[index] = item.PromiseResult;
// 全部都为成功时为成功
if(count === promises.length) {
resolve(resultArr);
}
}, r => {
reject(r);
});
});
})
}
// race方法
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach(item => {
item.then(v => {
resolve(v);
}, r => {
reject(r);
});
});
})
}