/**
* 判断then方法传入的参数是否是方法
* @param value 这里把then的参数传入
* @returns {boolean}
*/
const isFunction = (value) => typeof value === 'function';
class MyPromise {
constructor(executor) {
this.state = 'pending';//设置实例对象的state状态,默认是pedding
this.value = undefined;//储存resolve回调函数的value的值,的数据
this.reason = undefined;//储存reject的回调函数的reason的数据
this.onFullFilledCallbacks = [];//储存异步操作成功的回调函数
this.onRejectedCallbacks = [];//储存异步操作失败的回调函数
//设置成功回调函数
let resolve = (value) => {
this.state = 'fullFilled';
this.value = value;
/*当回调函数运行时,运行储存在数组中函数*/
this.onFullFilledCallbacks.forEach(fn => fn());
}
/*失败回调函数*/
let reject = (reason) => {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
// executor(resolve, reject);
/*try catch捕获异常,失败需要走reject*/
try {
executor(resolve, reject);
} catch (err) {
reject(err)
}
}
/**
*then方法
* @param onFullFilled 成功的回调
* @param onRejected 失败的回调
* @returns {MyPromise} 返回值是promise对象
*/
then(onFullFilled, onRejected) {
/*判断是否是方法,是方法就返回方法,不是方法,就组装成方法*/
onFullFilled = isFunction(onFullFilled) ? onFullFilled : data => data;
/*是方法返回方法,不是方法抛出错误*/
onRejected = isFunction(onRejected) ? onRejected : err => {
throw err;
};
/**
* 新建新的mypromie,用于返回,这是为了能够可以链式调用
* @type {MyPromise}
*/
const p2 = new MyPromise((resolve, reject) => {
let x;
if (this.state === 'fullFilled') {
/*让resolvePromise(p2, x, resolve, reject);之后再运行,因为让resolvePromise调用p2时,p2并没有没有生成*/
setTimeout(() => {
/*当异常时通过reject抛出异常*/
try {
x = onFullFilled(this.value);
// console.log(172, x);
resolvePromise(p2, x, resolve, reject);
} catch (err) {
reject(err)
}
}, 0)
/* x = onFullFilled(this.value);
// console.log('165:'+x)
// resolve(x);
resolvePromise(p2, x, resolve, reject)*/
}
if (this.state === 'rejected') {
setTimeout(() => {
try {
x = onRejected(this.reason);
resolvePromise(p2, x, resolve, reject);
} catch (err) {
reject(err)
}
}, 0)
}
if (this.state === 'pending') {
/* this.onFullFilledCallbacks.push(onFullFilled);
this.onRejectedCallbacks.push(onRejected);*/
/*存入成功的回调函数,观察者模式,先记录需要观察什么东西*/
this.onFullFilledCallbacks.push(() => {
setTimeout(() => {
try {
x = onFullFilled(this.value);
resolvePromise(p2, x, resolve, reject);
} catch (err) {
reject(err)
}
}, 0)
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
x = onRejected(this.reason);
resolvePromise(p2, x, resolve, reject);
} catch (err) {
reject(err)
}
}, 0)
/* x = onRejected(this.reason);
// resolve(x);
resolvePromise(p2, x, resolve, reject);*/
});
}
})
return p2;
}
}
/**
* 因为promise规范规定 x不能等于p2
* @param p2 then运行的返回值,promise
* @param x 成功失败函数运行返回的值,回调函数传入实参运行返回的值
* @param resolve 成功回调
* @param reject 失败回调
*/
function resolvePromise(p2, x, resolve, reject) {
// console.log(192, p2, x, resolve, reject);
// console.log(209,a);
//为了让回调函数执行一次上一把锁
let called;
if (p2 === x) {
reject(new TypeError('typeErr'));
}
/*x可以是个方法,再return出去一个值*/
if ((typeof x === 'object' && x != null) || x === 'function') {
try {
/*thenable对象,这是处理return new Promise的情况*/
let then = x.then;
if (typeof then === 'function') {
/* then.call(x是让then需要上下文,让then的上下文,变成x,变成
* 返回的promise,相当于返回的promise.then*/
then.call(x, y => {
/*x.then值是一样的*/
// x.then(y => {
/*这时then独立调用指向window*/
// then(y=>{
/*true时,走return直接终止函数运行,终止resolvePromise的运行,不是mypromise的运行*/
if (called) return;
called = true;
console.log(250, y);
resolve(y);
}, r => {
if (called) return;
called = true;
console.log(252, r);
reject(r);
})
} else {
if (called) return;
called = true;
resolve(x);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
/*这里不需要锁了*/
resolve(x);
}
}
/*
/!*换成mypromise*!/
// const p1 = new Promise((resolve, reject) => {
const p1 = new MyPromise((resolve, reject) => {
// setTimeout(() => {
resolve(1);
// reject(1);
// }, 1000)
})
const p2 = p1.then((res) => {
// console.log(res);
// return res + 1;
/!*返回值是一个Promise,想要拿到里面的reject,怎么拿到,需要通过得到它xx,
* xx.then的方式得到10*!/
return new MyPromise((resolve, reject) => {
reject(10);
})
}, err => {
// console.log(err)
return err + 2;
})
p2.then(res => {
console.log(266, res, 'success');
}, err => {
console.log(268, err, 'error');
})
*/
/*3 success*/
MyPromise.defer = MyPromise.deferred = function () {
let dfd = {};
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
module.exports = MyPromise;