Promise
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
status = PENDING;
value = null;
reason = null;
onFulfilledCallbacks = [];
onRejectedCallbacks = [];
resolve = value => {
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
while (this.onFulfilledCallbacks.length) {
this.onFulfilledCallbacks.shift()(value);
}
}
};
reject = reason => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
};
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
onRejected =
typeof onRejected === "function"
? onRejected
: reason => {
throw reason;
};
const promise2 = new MyPromise((resolve, reject) => {
const fulfilledMicrotask = () => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
const rejectedMicrotask = () => {
queueMicrotask(() => {
try {
const x = realOnRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
if (this.status === FULFILLED) {
fulfilledMicrotask();
} else if (this.status === REJECTED) {
rejectedMicrotask();
} else if (this.status === PENDING) {
this.onFulfilledCallbacks.push(fulfilledMicrotask);
this.onRejectedCallbacks.push(rejectedMicrotask);
}
});
return promise2;
}
static resolve(parameter) {
if (parameter instanceof MyPromise) {
return parameter;
}
return new MyPromise(resolve => {
resolve(parameter);
});
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
}
function resolvePromise(promise, x, resolve, reject) {
if (promise == x) {
return reject(new TypeError("Chaining cycle detected for promise #<Promise>"));
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
}
MyPromise.resolve()
.then(() => {
console.log(0);
return MyPromise.resolve(4);
})
.then(res => {
console.log(res);
});
- Promise.all:有 rejected 会直接返回并且只返回这个rejected,否则等全部返回
- Promise.allSettled(都解决的):全部执行完再返回,返回值里有 status [ “fulfilled” 或 “rejected” ]
- Promise.race(竞速的):返回第一个执行完的,不论是否 rejected
- Promise.any:返回第一个成功的,如果全部失败会进 catch
以上方法参数中有非 promise情况 则按成功状态处理
Promise.all
function promiseAll(args) {
const promises = Array.from(args);
const len = promises.length;
let count = 0;
let resultList = [];
return new Promise((resolve, reject) => {
function addToResultList(result, index) {
count++;
resultList[index] = result;
if (count === len) {
resolve(resultList);
}
}
promises.forEach((promise, index) => {
if (promise instanceof Promise) {
promise.then(result => {
addToResultList(result, index);
}, reject);
} else {
addToResultList(promise, index);
}
});
});
}
let pro1 = Promise.resolve(1);
let pro2 = 2;
let pro3 = Promise.resolve(3);
promiseAll([pro1, pro2, pro3])
.then(data => {
console.log("result", data);
})
.catch(err => {
console.log("err", err);
});
Promise.allSettled
function promiseAllSettled(args) {
const promises = Array.from(args);
const resultList = [];
const len = promises.length;
let count = 0;
return new Promise((resolve, reject) => {
if (len === 0) {
resolve(resultList);
}
function addToResultList(result, index) {
count++;
resultList[index] = result;
if (count === len) {
resolve(resultList);
}
}
promises.forEach((promise, index) => {
if (promise instanceof Promise) {
promise.then(
res => {
addToResultList(
{
status: "fulfilled",
value: res
},
index
);
},
err => {
addToResultList(
{
status: "rejected",
reason: err
},
index
);
}
);
} else {
addToResultList(
{
status: "fulfilled",
value: promise
},
index
);
}
});
});
}
const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => {
setTimeout(() => resolve(2), 1000);
});
const p3 = new Promise(resolve => {
setTimeout(() => resolve(3), 3000);
});
const p4 = Promise.reject("err4");
const p5 = Promise.reject("err5");
const p11 = promiseAllSettled([p1, p2, p4]).then(res =>
console.log(JSON.stringify(res, null, 2))
);
Promise.race
function promiseRace(args) {
const promises = Array.from(args);
return new Promise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof Promise) {
promise.then(
res => {
resolve(res);
},
err => {
reject(err);
}
);
} else {
resolve(promise);
}
});
});
}
let pro1 = Promise.resolve(1);
let pro2 = 2;
let pro3 = Promise.resolve(3);
promiseRace([pro1, pro2, pro3])
.then(data => {
console.log("result", data);
})
.catch(err => {
console.log("err", err);
});
Promise.any
function promiseAny(args) {
const promises = Array.from(args);
const len = promises.length;
let count = 0;
return new Promise((resolve, reject) => {
if (len === 0) return resolve([]);
promises.forEach(promise => {
if (promise instanceof Promise) {
promise.then(
res => {
resolve(res);
},
err => {
count++;
if (count === len) reject("All promises were rejected");
}
);
} else {
resolve(promise);
}
});
});
}
let pro1 = Promise.reject(1);
let pro2 = Promise.reject(1);
let pro3 = Promise.reject(3);
promiseAny([pro1, pro2, pro3])
.then(value => {
console.log("value: ", value);
})
.catch(err => {
console.log("err: ", err);
});