这部分是手写Promsie的重头戏,没看我手写Promise(上)的同学,请先看完
重头戏
- 紧接上回,我们把promise基本特点已经写完了,这篇开始写调用
.then
方法返回一个新的Promise实例等进阶的promise特点 .then
方法在调用时,里面有两个函数参数(onfulfilled和onrejected),分别是在promise实例成功/失败时调用。而且这两个函数的执行是否成功,也决定着返回的新的实例的状态。只要这个两个函数执行报错,那么新实例的就会执行rejec函数,变为失败状态。- 还有一点就是新的promise实例的状态也取决于返回的是否是一个新的promise实例来决定
.then
方法如果没传第一个函数参数或者第二个函数参数,系统默认传一个函数参数,成功的函数没传的话,直接传一个返回本身,失败的函数没传,就抛出一个异常,可以供下一个.then
继续执行
Promise.prototype = {
//是否是自定义
customize: true,
constructor: Promise,
// 执行then的时候,是异步执行,会返回一个新的Promise实例
then: function (onfulfilled, onrejected) {
//处理onfulfilled/onrejected不传值的情况
if (typeof onfulfilled !== 'function') {
onfulfilled = function onfulfilled(value) {
return value;
};
}
if (typeof onrejected !== 'function') {
onrejected = function onrejected(reason) {
throw reason;
};
}
//self是原始promise实例
var self = this;
//promise是新的promise实例
var promise=new Promise(function(resolve,reject){
switch (self.PromiseState) {
//知道状态的情况
case 'fullfilled':
setTimeout(function () {
try {
var x = onfulfilled(self.PromiseResult);
resolvePromise(promise, x, resolve, reject);
//还得判断x是不是promise实例
} catch (err) {
//报错就执行reject
reject(err);
}
});
break;
case 'rejected':
setTimeout(function () {
try {
var x = onrejected(self.PromiseResult);
resolvePromise(promise, x, resolve, reject);
} catch (error) {
reject(error);
}
});
break;
/*
不知道实例状态的时候(executor函数中是一个异步操作)
此时我们应该把基于then传入的方法存起来,在执行resolve/reject函数时,通知其执行
*/
default:
// self.onFulfilledCallbacks.push(onfulfilled);
// self.onRejectedCallbacks.push(onrejected);
//存放匿名函数的好处就是可以接收onfulfilled/onrejected返回值,判断其是否报错
self.onFulfilledCallbacks.push(function (PromiseResult) {
try {
var x = onfulfilled(PromiseResult);
resolvePromise(promise, x, resolve, reject);
} catch (error) {
reject(error);
}
});
self.onRejectedCallbacks.push(function (PromiseResult) {
try {
var x = onrejected(PromiseResult);
resolvePromise(promise, x, resolve, reject);
} catch (error) {
reject(error);
}
});
break;
}
})
//返回一个新的promise实例
return promise;
}
}
-
这是统一处理基于then返回新实例的成功和失败
-
首先判断返回值和当前的创建的新实例是否一样,一样的话就会产生死循环。
-
根据Promise A+ 规范知道,是否是一个promise实例,有几点条件
- 必须是函数或者对象
- 必须有
.then
方法
-
这样的话,如果
.then
方法的两个函数参数的返回值不是一个promise实例的话,直接就把新的promise实例就变为成功态了,如果是一个promise实例,则必须判断是否满足以上的条件,然后再根据执行resolve/reject判断新的promise实例的状态
/*
promise:处理的那个promise实例
x:执行onfulfilled/onrejected拿到的结果
resolve:promsie变成功
reject:promise变失败
*/
//统一处理基于then返回新实例的成功和失败
function resolvePromise(promise, x, resolve, reject) {
//如果返回值和当前的创建的新实例一样,形成死循环
if (x === promise) {
throw new TypeError('Chaining cycle detected for promise #<Promise>');
}
if ((x !== null && typeof x === 'object') || typeof x === 'function') {
try {
var then = x.then;
if (typeof then === 'function') {
//走到这一步,返回结果一定是一个新的promsie实例
then.call(
x,
function (y) {
resolve(y);
},
function (r) {
reject(r);
}
);
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
}