本文上篇链接: 从深入理解到自定义Promise–上篇
定义整体结构
/*Promise构造函数*/
function MyPromise(excutor) {
}
/*构造方法*/
/*返回一个指定成功value的promise对象*/
MyPromise.resolve = function (value) {
}
/*返回一个指定失败reason的promise对象*/
MyPromise.reject = function(reason) {
}
/*返回一个promise,只有列表中所有的promise都成功才算最终成功*/
MyPromise.all = function(promiseList) {
}
/*返回一个promise,一旦列表中某个promise解决或拒绝了,返回这个结果*/
MyPromise.race = function(promiseList){
}
/*实例方法*/
/*为promise指定成功/失败的回调,返回一个新的promise对象*/
MyPromise.prototype.then = function (onResolve,onRejected) {
}
/*为promise指定失败的回调,返回一个新的promise对象*/
MyPromise.prototype.catch = function(onRejected) {
}
module.exports = MyPromise;
完成构造函数的实现
在构造函数Promise中
第一步 同步调用执行器函数
(需要声明resolve,reject函数)
excutor(resolve,reject);
function resolve(data) {};
function reject(data) {};
第二步 设计resolve,reject函数 (调用resolve函数或reject函数时会改变状态)
this.status = "pending";
this.result = null;
//保存实例对象的this值
const that = this;
function resolve(data) {
//改变实例对象的状态
that.status = "resolved";
//改变状态的同时保存结果
that.result = data;
}
function reject(data) {
//改变实例对象的状态
that.status = "rejected";
//改变状态的同时保存结果
that.result = data;
}
第三步 完善状态改变方案
//考虑到throw 抛出异常时,状态改变为rejected,改写执行器调用部分为
try {
excutor(resolve,reject);
} catch(err) {
reject(err);
}
//考虑到状态只能修改一次,修改函数如下
function resolve(data) {
if(that.status !== "pending") return;
//改变实例对象的状态
that.status = "resolved";
//改变状态的同时保存结果
that.result = data;
}
function reject(data) {
if(that.status !== "pending") return;
//改变实例对象的状态
that.status = "rejected";
//改变状态的同时保存结果
that.result = data;
}
Promise.then/catch的实现
在实例方法Promise.prototype.then中
第一步 调用onResolved,onRejected回调函数
Promise.prototype.then = function (onResolved,onRejected) {
if(this.status === "resolved") {
onResolved(this.result);
}else if(this.status === "rejected") {
onRejected(this.result);
}
}
第二步 实现先指定回调函数,后改变状态
目前为止,自定义的promise还不具备先定义回调函数后改状态的能力
解决方法:在构造函数中定义属性callback,在实例方法里面.判断status为pending时,保存回调函数到callback中
构造函数Promise中添加
//添加属性保存回调函数
this.callback = {};
//当回调函数存在,就调用
function resolve(data) {
//...省略前面代码
that.callback.onResolved && that.callback.onResolved(data);
}
function reject(data) {
//...省略前面代码
that.callback.onRejected && that.callback.onRejected(data);
}
在实例方法Promise.prototype.then中添加
else if(this.status === "pending") {
this.callback = {
onResolved,
onRejected
};
}
第三步 解决保存回调的缺陷
上述代码保存回调的方法,只是个调用一次then时保存
同一个promise对象保存不同回调时,保存的是最后一次的回调
构造函数Promise中修改
//添加属性保存回调函数
this.callback = [];
//遍历数组调用
function resolve(data) {
//...省略前面代码
that.callback.forEach(item => {item.onResolved(data)})
}
function reject(data) {
//...省略前面代码
that.callback.forEach(item => {item.onRejected(data)})
}
在实例方法Promise.prototype.then中修改
else if(this.status === "pending") {
this.callback.push({
onResolved,
onRejected
});
}
第四步 实现then方法返回结果
Promise.prototype.then = function (onResolved,onRejected) {
const that = this;
//返回的结果必须的promise对象
return new Promise((resolve,reject) => {
//封装函数
function callback(fn){
try{
//先拿到结果,然后按结果分类处理
let result = fn(that.result);
//结果如果是promise对象
if(result instanceof Promise) {
result.then(value => {
resolve(value);
},reason => {
reject(reason);
})
}else {
resolve(result);
}
}catch(err) { //如果是抛出异常
reject(err)
}
}
//如果状态是resolved
if(this.status === "resolved") {
fn(onResolved);
}
//如果状态是rejected
else if(this.status === "rejected") {
fn(onRejected);
}
//如果状态是pending
else if(this.status === "pending") {
this.callback.push({
onResolved,
onRejected
});
}
})
}
第五步 解决异步情况,返回结果的状态是pending情况
//如果状态是pending
return new Promise((resolve,reject) => {
//...
else if(this.status === "pending") {
this.callback.push({
onResolved:function(){
fn(onResolved);
},
onRejected:function(){
fn(onRejected);
}
});
}
}
添加catch方法
在Promise.prototype.catch中添加
第一步 实现catch功能
Promise.prototype.catch = function (onRejected){
return this.then(null,onRejected);
}
在Promise.prototype.then中添加
第二步 实现异常穿透 和 值传递
Promise.prototype.then= function (onResolve,onRejected){
const that = this;
if(typeof onResolved !== "function") {
onResolved = value => value;
}
if(typeof onRejected !== "function") {
onRejected = reason => {
throw reason;
}
}
//...
Promise.resolve/reject的实现
…后续补充
Promise.all/race的实现
…后续补充