const PENDING = 'pending',
SUCCESS = 'success',
FAILED = 'failed';
const resolvePromise = (newPromise, x, res, rej) => {
if (newPromise === x) rej(new TypeError('Chaining cycle detected for promise #<Promise>'));
let called;
if (typeof x === 'function' || (typeof x === 'object' && x !== null)) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x,
y => {
if (called) return;
called = true;
resolvePromise(newPromise, y, res, rej)
},
e => {
if (called) return;
called = true;
rej(e)
}
);
} else {
res(x)
}
} catch (error) {
if (called) return;
called = true;
rej(x)
}
} else {
res(x)
}
}
function isPromise(value) {
if (typeof value === 'function' || (typeof value === 'object' && value !== null)) {
if (typeof value.then === 'function') {
return true;
}
}
return false;
}
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
this.err = null;
this.onFCB = [];
this.onRCB = [];
let resolve = value => {
if (this.status === PENDING) {
this.status = SUCCESS;
this.value = value;
this.onFCB.forEach(fn => fn(this.value));
}
}
let reject = err => {
if (this.status === PENDING) {
this.status = FAILED;
this.err = err;
this.onRCB.forEach(fn => fn(this.err));
}
}
try {
executor(resolve, reject);
} catch (error) {
reject(error)
}
}
then(onF, onR) {
onF = typeof onF === 'function' ? onF : val => val;
onR = typeof onR === 'function' ? onR : err => {
throw err; Î
}
let newPromise;
newPromise = new Promise((res, rej) => {
switch (this.status) {
case SUCCESS:
setTimeout(() => {
try {
let x = onF(this.value);
resolvePromise(newPromise, x, res, rej);
} catch (error) {
rej(error)
}
})
return;
case FAILED:
setTimeout(() => {
try {
let x = onR(this.err);
resolvePromise(newPromise, x, res, rej);
} catch (error) {
rej(error)
}
})
return;
case PENDING:
this.onFCB.push(() => {
setTimeout(() => {
try {
let x = onF(this.value);
resolvePromise(newPromise, x, res, rej);
} catch (error) {
rej(error)
}
})
})
this.onRCB.push(() => {
setTimeout(() => {
try {
let x = onR(this.err);
resolvePromise(newPromise, x, res, rej);
} catch (error) {
rej(error)
}
})
})
return;
default:
return;
}
})
return newPromise;
}
}
// 实现promise catch finally all race resolve reject
// catch then语法糖
Promise.prototype.catch = function (cb) {
return this.then(null, cb);
}
// resolve 少包一层 直接返回一个promise实例并执行成功传入value
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
resolve(value);
})
}
// reject 少包一层 直接返回一个promise实例并执行成功传入value
Promise.reject = function (e) {
return new Promise((resolve, reject) => {
reject(e);
})
}
// finally 无论如何都执行
Promise.prototype.finally = function (cb) {
return this.then(
value => { // 无论正确还是失败都走这个回调,为了保证cb执行后在进行下一步,利用promise的res方法有等待异步执行的特点
return Promise.resolve(cb()).then(() => value);
},
e => {
return Promise.resolve(cb()).then(() => { throw e }); // koa 原理
}
)
}
// 多个promise按顺序获取对应的值
Promise.all = function () {
return new Promise((resolve, reject) => { //首先建立一个promise
let arr = []; // arr[3] = 2 arr.length = 4
let i = 0;
let processData = (key, value) => {
arr[key] = value; // after函数
if (++i === values.length) { // 直到全部异步都执行完毕在去调用res方法返回对应数据
resolve(arr);
}
}
// 循环执行每一个异步调用
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (isPromise(current)) { // 如果是promise那么就执行then拿到结果
current.then(y => {
processData(i, y);
}, reject);
} else {
processData(i, current); // 如果不是直接把值传出去
}
}
})
}
// 多个promise 看那个执行速度最快不管成功失败都返回最快的那个执行结果
Promise.race = function (values) {
return new Promise((resolve, reject) => {
// 循环所有值
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (isPromise(current)) { // 是promise执行这个promise
current.then(resolve, reject);
} else { // 不是的话直接返回这个值
resolve(current);
}
}
})
}Ï
手动实现promise 及 常用方法
最新推荐文章于 2024-04-26 09:23:58 发布