推荐一个写Promise的规范文档:
开始实现简单版本的promise:
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class Promise {
constructor(excuctor) {
this.status = PENDING;
this.value = undefined; // 存放成功的值
this.reason = undefined; // 存放失败的值
this.fulfillCallbacks = [];
this.rejectCallbacks = [];
let resolve = (value) => {
// 只有状态是等待的时候才可以转换成其他状态
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.fulfillCallbacks.forEach(fn => fn())
}
}
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.rejectCallbacks.forEach(fn => fn())
}
}
try {
excuctor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
// 同步
if (this.status === FULFILLED) {
return onFulfilled(this.value)
}
// 同步
if (this.status === REJECTED) {
return onRejected(this.reason)
}
// 异步
if (this.status === PENDING) {
this.fulfillCallbacks.push(() => {
onFulfilled(this.value)
})
this.rejectCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
module.exports = Promise
上面的实现并没有考虑then的回调中返回promise的情况,所以下面的代码会着重实现这一块逻辑
1.如果then的成功或者失败回调中返回的还是promise,会等待这个promise执行结果 并将结果传给下一个then的成功时的参数中
2.只有两种情况会走下一个then的失败回调:
1.如果then的成功或者失败回调抛出异常 则走下一个then的失败回调
2.如果then的成功或者失败回调返回一个失败的promise
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
//核心方法
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError('x 不能等于 promise2'))
}
if (typeof x === 'object' && x !== null) {
try {
let then = x.then; // 取then的时候可能发生异常 别人用Object.defineProperty定义的
if (typeof then === 'function') {
// 确定x是promise,然后执行这个promise
// then.call的方式可以减少再次取x.then的值 因为可能再次取会出现问题
then.call(x, (y) => {
// y可能还会是promise
// resolvePromise(promise2, y, resolve, reject) resolve的时候已经判断了
resolve(y)
}, (r) => {
reject(r)
})
} else {
// x是普通值
resolve(x)
}
} catch (error) {
reject(error)
}
} else {
resolve(x)
}
}
class Promise {
constructor(excuctor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.fulfillCallbacks = [];
this.rejectCallbacks = [];
let resolve = (value) => {
// 如果value是一个promise
if (value instanceof Promise) {
return value.then(resolve, reject)
}
// 只有状态是等待的时候才可以转换成其他状态
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.fulfillCallbacks.forEach(fn => fn())
}
}
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.rejectCallbacks.forEach(fn => fn())
}
}
try {
excuctor(resolve, reject)
} catch (error) {
reject(error)
}
}
// x 是当前then的成功或者失败回调的返回结果
// 如果x是普通值 直接传递到下一个then中
// 如果x是promise 需要拿到这个promise的状态
// 执行时抛出错误直接 调用promise2的reject
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }
// 每次调用then都需要返回一个新的实例 保证状态不影响
let promise2 = new Promise((resolve, reject) => {
// 同步
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
// resolvePromise 判断x是普通值还是promise 然后做一些操作
resolvePromise(promise2, x, resolve, reject)
// resolve(x) // 这种只能处理x是普通值的情况
} catch (error) {
reject(error)
}
});
}
// 同步
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
});
}
// 异步
if (this.status === PENDING) {
this.fulfillCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
});
})
this.rejectCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
});
})
}
})
return promise2
}
}
module.exports = Promise
promise的常用静态方法和原型方法的实现:
static reject(error) {
return new Promise((resolve, reject) => {
reject(error)
})
}
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
static all(promises) {
return new Promise(function (resolve, reject) {
let results = [];
let j = 0;
let promisesLength = promises.length;
for (let i = 0; i < promisesLength; i++) {
Promise.resolve(promises[i]).then(res => {
results[i] = res;
// 当所有函数都正确执行了,resolve输出所有返回结果。
if (++j === promisesLength) {
resolve(results);
}
}, reject);
}
});
}
static race(promises) {
return new Promise((resolve, reject) => {
for (let promise of promises) {
Promise.resolve(promise).then(resolve, reject)
}
})
}
static allSettled(promises) {
return new Promise((resolve) => {
let results = []
let index = 0;
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then((val) => {
results[i] = { status: FULFILLED, value: val }
if (++index === promises.length) { resolve(results) }
}, err => {
results[i] = { status: REJECTED, reason: err }
if (++index === promises.length) { resolve(results) }
})
}
})
}
static any(promises) {
return new Promise((resolve, reject) => {
let index = 0;
let reasons = []
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(resolve, (err) => {
reasons[i] = err
if (++index === promises.length) {
reject(new AggregateError(reasons))
}
})
}
})
}
finally(callback) {
return this.then((val) => {
// callback()
// return val
// Promise.resolve具备等待效果
return Promise.resolve(callback()).then(() => val)
}, (err) => {
return Promise.resolve(callback()).then(() => {
throw err
})
})
}
catch(errCallback) {
return this.then(null, errCallback)
}