1. 代码思路
1.1 整体思路
Promise的链式调用核心就是发布订阅者模式。 就是将then后面的方法作为回调函数注册到一个任务队列当中去,等到reslove或者reject方法执行完毕之后,将对应任务队列然后再执行任务队列中的函数。
因此当我们我们将reslove和reject放到异步任务中,等到异步任务执行完毕之后,将结果保存到reslove和reject,这时候Promise开始执行任务队列中的回到函数,达到链式调用的效果。
1.2 先写架构
Promise 传入一个execute方法,这个方法接受两个参数,resolve和reject
Promise 常量:三个状态 PENDING RESOLVED REJECTED
Promise 变量:状态state,执行结果value,以及resolve和reject执行结束后的回调方法队列
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
function MyPromise(execute) {
this.state = PENDING;
this.value = null;
this.resolvedcallBack = [];
this.rejectedCallBack = [];
function resolve(value) {
}
function reject(value) {
}
try {
execute(resolve, reject);
} catch (err) {
reject(err)
}
}
1.3 resolve(value)
因为使用的是构造函数实现,所以是self保留this对象,值得函数内部能够调用this的属性。
这一步考虑resolve(value)中的value值是Promise对象的情况,并延迟执行resove方法。
realove方法的执行放在setTimeout里面,保证reslove异步执行顺序。
function resolve(value) {
//value是一个promise,则状态改变需要等待前一个状态改变,等上一函数执行完之后,再执行reslove
if (value instanceof MyPromise) {
return value.then(resolve, reject);
}
// resolve 异步执行
setTimeout(function () {
self.state = RESOLVED;
self.value = value;
self.resolvedcallBack.forEach((callBack) => {
callBack(value);
});
}, 0)
}
1.3 then() 不添加链式调用
MyPromise.prototype.then = function (onResolved, onRejected) {
// 如果没有参数或者不是一个function,赋予一个默认函数
onResolved = typeof (onResolved) === 'function' ? onResolved : function (data) {
return data;
}
onRejected = typeof (onRejected) === 'function' ? onRejected : function (err) {
return err;
}
//如果异步执行
if (this.state === PENDING) {
this.resolvedcallBack.push(onResolved);
this.rejectedCallBack.push(onRejected);
}
//如果同步执行
if (this.state === RESOLVED) {
this.resolvedcallBack.push(onResolved);
}
if (this.state === REJECTED) {
this.rejectedCallBack.push(onRejected);
}
}
1.4 then() 添加链式调用
链式调用是什么?客官请看,下面这个代码,能够输出 then,2 ,就是链式调用。其实很简单,我们只需要稍微包装一下下,就功德圆满了。
new MyPromise((resolve, reject) => {
resolve('1');
}).then(data => {
console.log('yes', data);
return 2;
}).then(data=>{
console.log('then',data)
})
就是then方法执行完默认返回一个promise对象,并且这个promise对象肯定得有resolve或者reject点什么东西?
肯定是reslove或者reject then(onResolved, onRejected)方法两个回调函数的返回值了。
-
所以第一步,
then方法里面先return一个Promise对象,第一个需求完成了。 -
然后第二步,这下我们不直接将
onResolved, onRejected两个方法放到队列了放什么呢?我们将这两个函数封装一下,封装成一个新函数rejected和rejected,这个新函数里面同样会执行会执行onResolved, onRejected两个方法,同样也还是会将执行后的返回值reslove或者reject起来,第二件大事也完成了,功德圆满。
MyPromise.prototype.then = function (onResolved, onRejected) {
onResolved = typeof (onResolved) === 'function' ? onResolved : function (data) {
return data;
}
onRejected = typeof (onRejected) === 'function' ? onRejected : function (err) {
return err;
}
const self = this;
return new MyPromise((resolve, reject) => {
// 对then中的函数进行进一步的封装,then方法的执行结果,使用resolve保存起来
let resolved = function () {
try {
const result = onResolved(self.value);
// 返回的是resolve(result)
return resolve(result);
} catch (err) {
reject(err);
}
}
let rejected = function () {
try {
const result = onRejected(self.value);
// 返回的是resolve(result)
return reject(result);
} catch (err) {
reject(err);
}
}
//如果异步执行
if (this.state === PENDING) {
this.resolvedcallBack.push(resolved);
this.rejectedCallBack.push(rejected);
}
//如果同步执行
if (this.state === RESOLVED) {
this.resolvedcallBack.push(resolved);
}
if (this.state === REJECTED) {
this.rejectedCallBack.push(rejected);
}
})
}
2. 全部代码
const PENDING = "pending";
const RESOLVE = 'resolve';
const REJECT = 'reject';
function MyPromise(execute) {
let self = this;
this.state = PENDING;
this.value = null;
this.resoleCallBack = [];
this.rejectCallBack = [];
function resolve(value) {
if (value instanceof MyPromise) return value.then(resolve, reject());
setTimeout(function () {
if (self.state === PENDING) {
self.state = RESOLVE;
self.value = value;
self.resoleCallBack.forEach((callBack) => {
callBack(value);
})
}
}, 0)
}
function reject(value) {
if (value instanceof MyPromise) return value.then(resolve, reject());
setTimeout(function () {
if (self.state === PENDING) {
self.state = REJECT;
self.value = value;
self.rejectCallBack.forEach((callBack) => {
callBack(value);
})
}
}, 0)
}
try {
execute(resolve, reject)
} catch (e) {
reject(e);
}
}
MyPromise.prototype.then = function (onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : function (value) {
return value;
}
onRejected = typeof onRejected === 'function' ? onRejected : function (err) {
return err;
}
if (this.state === PENDING) {
this.resoleCallBack.push(onResolved);
this.rejectCallBack.push(onRejected);
}
if (this.state === RESOLVE) {
onResolved(this.value);
}
if (this.state === REJECT) {
onRejected(this.value);
}
}
new MyPromise((resolve, reject) => {
reject('err');
}).then(data => {
console.log('yes',data);
},err=>{
console.log("no",err)
})