/*
自定义promise
1. 执行MyPromise构造函数,要立即执行executor
2. promise实例对象,内部有三种状态
初始化 pending
成功 resolved
失败 rejected
注意:状态只能修改一次
如果executor内部出错了,promise状态改成rejected
3. then方法的实现
promise.then(onResolved, onRejected)
promise的状态是resolved时,异步调用onResolved函数
promise的状态是rejected时,异步调用onRejected函数
promise的状态是pending时,不调用函数。
未来promise可能会变化,此时还是要异步调用相应的函数
4. promise.then().then()
then方法返回值是promise,才能链式调用
返回值promise对象的状态:
1. 如果内部没有返回值 / 返回值不是promise 就是resolved
2. 如果内部返回值是promise 看promise的状态
3. 如果内部抛异常,就是rejected
*/
function MyPromise(executor) {
this._value = undefined;
this._status = 'pending';
this._callbacks = [];
const resolve = (value) => {
if (this._status === 'pending') {
this._status = 'resolved';
this._value = value;
this._callbacks.length &&
this._callbacks.forEach((cb) => cb.onResolve(value));
}
};
const reject = (reason) => {
if (this._status === 'pending') {
this._status = 'rejected';
this._value = reason;
this._callbacks.length &&
this._callbacks.forEach((cb) => cb.onReject(reason));
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
MyPromise.prototype.then = function (onResolve, onReject) {
// 如果onResolved存在,不变
// 如果onResolved不存在,说明catch触发的。 如果是成功状态promise,保证返回值还是一个成功状态promise
onResolve = onResolve ? onResolve : (value) => value;
// then方法一旦只传一个参数,并且是失败状态promise,保证返回值 是 失败状态promise内部的值
onReject = onReject
? onReject
: (reason) => {
throw reason;
};
return new MyPromise((resolve, reject) => {
setTimeout(() => {
switch (this._status) {
case 'resolved':
setPromiseStatus(onResolve, this._value, resolve, reject);
break;
case 'rejected':
setPromiseStatus(onReject, this._value, resolve, reject);
break;
default:
this._callbacks.push({
onResolve(value) {
setPromiseStatus(onResolve, value, resolve, reject);
},
onReject(reason) {
setPromiseStatus(onReject, reason, resolve, reject);
},
});
break;
}
});
});
};
function setPromiseStatus(onFn, value, resolve, reject) {
try {
let result = onFn(value);
result instanceof MyPromise
? result.then(resolve, reject)
: resolve(result);
} catch (e) {
reject(e);
}
}
MyPromise.prototype.catch = function (onReject) {
return this.then(undefined, onReject);
};
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => {
resolve(value);
});
};
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
};
MyPromise.prototype.finally = function (onResolve) {
return new MyPromise((resolve, reject) => {
if (this._status === 'pending') {
this._callbacks.push({
onResolve,
onReject: onResolve,
});
} else {
onResolve(this._value);
}
});
};
MyPromise.all = function (promises) {
let resolveCount = 0,
resolveArr = [];
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
const element = promises[i];
element.then((value) => {
resolveCount++;
resolveArr[i] = value;
if (resolveCount === promises.length) {
resolve(resolveArr);
}
}, reject);
}
});
};
let p = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve(123);
reject(0);
// }, 1000);
});
p.then((value) => {
console.log(111, value);
})
.catch((value) => {
console.log(222, value);
})
.then((value) => {
console.log(333, value);
return MyPromise.reject(999);
})
.catch((value) => {
console.log(444, value);
})
.finally((value) => {
console.log(555, value);
});
// console.log(p);
// console.log(MyPromise.resolve(123));
// 测试promise.all
const p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(111);
}, 2000);
});
const p2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(222);
}, 2000);
});
let a = MyPromise.all([p1, p2]);
console.log(a);