JS手写Promise
Promise是异步编程的一种解决方案,简单的来说,Promise作为一个容器,保存着某个未来才会结束的事件的结果。
Promise有两个特点:
1)对象的状态不受外界影响。Promise有三种状态:pengding(进行中),fulfilled(完成),rejected(失败),只有异步操作的结果,可以决定当前是哪一个状态。
2)一旦状态改变,就不再改变。
class MyPromise {
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
constructor(executor) { // executor 执行器
this.status = MyPromise.PENDING; // 状态
this.value = undefined; // 成功值
this.reason = undefined; // 失败理由
this.onFulfilled = [];
this.onRejected = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (err) {
this.reject(err);
}
}
resolve(value) {
if (this.status === MyPromise.PENDING) {
setTimeout(() => {
this.status = MyPromise.FULFILLED;
this.value = value;
this.onFulfilled.forEach(fn => fn(value));
}, 0)
}
}
reject(reason) {
if (this.status === MyPromise.PENDING) {
setTimeout(() => {
this.status = MyPromise.REJECTED;
this.reason = reason;
this.onRejected.forEach(fn => fn(reason))
}, 0)
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
let handler = (callback) => {
try {
let result = callback(this.value);
if (result instanceof MyPromise) { // 如果结果是Promise
result.then(resolve, reject); // 返回一个Promise
} else { // 如果结果不是Promise
resolve(result);// 直接resolve 结果
}
} catch (err) {
reject(err)
}
}
if (this.status === MyPromise.FULFILLED) {
handler(onFulfilled)
}
if (this.status === MyPromise.REJECTED) {
handler(onRejected)
}
if (this.status === MyPromise.PENDING) {
typeof onFulfilled == 'function' && this.onFulfilled.push(onFulfilled)
typeof onRejected == 'function' && this.onRejected.push(onRejected)
}
});
}
static resolve(promises) {
if (promises instanceof MyPromise) { // 如果参数是MyPromise 实例,那么MyPromise.resolve将不做任何修改、原封不动地返回这个实例。
return promises;
} else if (typeof promises.then === 'function') {
return new MyPromise((resolved, rejected) => {
try {
promises.then(resolved, rejected);
} catch (err) {
rejected(err);
}
})
} else {
// 如果参数是一个原始值,或者是一个不具有then()方法的对象
// Promise.resolve()方法返回一个新的 Promise 对象,状态为resolved
return new MyPromise((resolved, rejected) => {
resolved(promises);
})
}
}
static reject(reason) {
return new MyPromise((resolved, rejected) => {
rejected(reason);
})
}
static all(promises) {
if (!Utils.isIterable(promises)) {
throw new TypeError("Object is not iterable");
}
let values = [];
return new MyPromise((resolved, rejected) => {
promises.map(v => {
let item = v;
if (!(v instanceof MyPromise)) item = MyPromise.resolve(item)
item.then(res => {
values.push(res);
if (values.length == promises.length) {
resolved(res);
}
}, err => {
rejected(err)
})
})
})
}
static race(promises) {
if (!Utils.isIterable(promises)) {
throw new TypeError("Object is not iterable");
}
return new MyPromise((resolved, rejected) => {
promises.map(v => {
let item = v;
if (!(v instanceof MyPromise)) item = MyPromise.resolve(item)
item.then(res => {
resolved(res);
}, error => {
rejected(error);
})
})
})
}
catch(rejected) {
this.then(undefined, rejected)
}
finally(callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
)
}
}
class Utils { // 工具类
static isIterable(object) { // object是否可迭代
return typeof object[Symbol.iterator] === 'function'
&& typeof object[Symbol.iterator]() === 'object'
&& typeof object[Symbol.iterator]().next === 'function'
}
}