什么是Promise
在现代开发过程中,异步请求已经成为我们无法避免的问题。之前解决异步请求都是通过回调函数的方式,但是这会造成回调地狱的问题。Promise出现之后,我们可以通过链式调用能够很轻松去避免回调过深的问题,同时Promise也给我们提供了非常良好的一些方法,可以供我们去使用。例如 Promise.all(),Promise.allSettled(),Promise.any(),Promise.race()这四个单例方法,那么今天就给大家手写一下Promise以及他提供的这些方法。
Promise
class MyPromise {
constructor(callback) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];
this.resolve = (value) => {
if (this.state === "pending") {
this.state = "fullfilled";
this.value = value;
this.onResolveCallbacks.forEach(fn => fn());
}
}
this.reject = (reason) => {
if (this.state === "pending") {
this.state = "reject";
this.reason = reason;
this.onRejectCallbacks.forEach(fn => fn());
}
}
callback(this.resolve, this.reject);
}
then(onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason };
const newPromise = new MyPromise((resolve, reject) => {
if (this.state === "fullfilled") {
try {
const x = onResolved(this.value);
resolve(x);
} catch (err) {
reject(err);
}
}
if (this.state === "reject") {
try {
// 执行 onRejected 回调函数
const x = onRejected(this.reason);
// 处理返回值
resolve(x);
} catch (err) {
reject(err);
}
}
if (this.state === "pending") {
this.onResolveCallbacks.push(() => {
try {
//
const x = onResolved(this.value);
resolve(x);
} catch (error) {
reject(error)
}
})
this.onRejectCallbacks.push(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error)
}
})
} else {
this.onRejectCallbacks = [];
this.onResolveCallbacks = [];
}
})
return newPromise;
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(callback) {
return this.then(
value => resolve(callback()).then(() => value),
reason => resolve(callback()).then(() => { throw reason })
);
}
static all(arr) {
if (!Array.isArray(arr)) {
throw new Error('param is not array')
}
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
arr.forEach((item, index) => {
if (item instanceof MyPromise) {
item.then(res => {
result[index] = res;
count++;
if (count === arr.length) {
return resolve(result);
}
}, err => {
return reject(err);
})
} else {
result[index] = item;
count++;
if (count === arr.length) {
return resolve(result);
}
}
})
})
}
static allSettled(arr) {
if (!Array.isArray(arr)) {
throw new Error('param is not array');
}
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
arr.forEach((item, index) => {
if (item instanceof MyPromise) {
item.then(res => {
result[index] = res;
count++;
if (count === arr.length) {
return resolve(result);
}
}, err => {
result[index] = err;
count++;
if (count === arr.length) {
return resolve(result);
}
})
} else {
result[index] = item;
count++;
if (count === arr.length) {
return resolve(result);
}
}
})
})
}
static race(arr) {
if (!Array.isArray(arr)) {
throw new Error('param is not array');
}
return new MyPromise((resovle, reject) => {
arr.forEach(item => {
if (item instanceof MyPromise) {
item.then(res => {
return resovle(res);
}, err => {
return reject(err);
})
} else {
return resovle(item)
}
})
})
}
static any(arr) {
if (!Array.isArray(arr)) {
throw new Error('param is not array')
}
return new MyPromise((resolve, reject) => {
let count = 0;
let rejects = [];
arr.forEach((item, index) => {
if (item && typeof item.then === 'function') {
item.then(data => {
return resolve(data) // 使用最先成功的结果
}, err => {
rejects[index] = err;
count++;
if (count === arr.length) {
return reject(rejects);
}
})
} else {
// 处理普通值,直接成功
return resolve(item);
}
})
})
}
}
上述是一个完整的Promise 代码,那么下面我解析一下这段代码。
constructor
constructor(callback) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onResolveCallbacks = [];
this.onRejectCallbacks = [];
this.resolve = (value) => {
if (this.state === "pending") {
this.state = "fullfilled";
this.value = value;
this.onResolveCallbacks.forEach(fn => fn());
}
}
this.reject = (reason) => {
if (this.state === "pending") {
this.state = "reject";
this.reason = reason;
this.onRejectCallbacks.forEach(fn => fn());
}
}
callback(this.resolve, this.reject);
}
在构造函数中我们接受一个callback 作为参数,同时分别定义了 state,value,reason,onResolveCallbacks,onRejectCallbacks,resolve,reject这些元素,他们分别对应Promise的状态、成功值、失败原因、成功后的回调列表、失败后的回调列表等等。