# blog_demo_lpromise **Repository Path**: layouwen/blog_demo_lpromise ## Basic Information - **Project Name**: blog_demo_lpromise - **Description**: 一步步实现一个Promise - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-17 - **Last Updated**: 2021-04-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 1、前言 本篇文章,默认你已经知道什么是 **Promise** ,然后我会带你一步步的实现一个简易的 Promise。将会以循序渐进的方式,分步骤实现。 本文章相关代码地址:[https://github.com/layouwen/blog_demo_lpromise](https://github.com/layouwen/blog_demo_lpromise) 如果本文章对你有所帮助,请不要吝啬你的 **Start** 哦~ ## 2、三种状态 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E4%B8%89%E7%A7%8D%E7%8A%B6%E6%80%81.html) Promise 它一共会有三种状态: 1. pending 2. fulfilled 3. rejected 下面我们自己实现一个类,默认为 **pending** 状态,通过调用 **resolve** 或者 **reject** 改变其状态 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err } } console.log(new LPromise((resolve, reject) => console.log('pending'))) // pending 状态 const l1 = new LPromise((resolve, reject) => { resolve('我调用了resolve') }) console.log(l1) // fulfilled 状态 const l2 = new LPromise((resolve, reject) => { reject('我调用了reject') }) console.log(l2) // rejected 状态 ``` ## 3、实现 then 参数回调 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E5%AE%9E%E7%8E%B0then%E5%8F%82%E6%95%B0%E5%9B%9E%E8%B0%83.html) 返回的 **Promise** ,可以通过使用 **then** 传递成功和失败的回调。 通过 then 接收了两个回调。实现了分别调用回调的内容。但是发现,他们两个都会执行。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err } /* new content start */ then(onResolve, onReject) { onResolve() onReject() } /* new content end */ } const l1 = new LPromise((resolve, reject) => resolve()) l1.then( res => console.log('res'), err => console.log('err') ) ``` 对执行时机进行调整。使其在调用 resolve 或 reject 才执行相关的回调 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res /* new content start */ this.cbResolve() // 报错 /* new content end */ } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err /* new content start */ this.cbReject() // 报错 /* new content end */ } then(onResolve, onReject) { /* new content start */ this.cbResolve = onResolve this.cbReject = onReject /* new content end */ } } const l1 = new LPromise((resolve, reject) => resolve()) l1.then( res => console.log('res'), err => console.log('err') ) ``` 改装后,发现 resolve 和 reject 的执行时间比 then 的回调要快。导致无法执行 then 中的回调。我们需要对 resolve 和 reject 中执行回调的部分进行 **延迟执行**。可以使用 setTimeout 进行延迟 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res /* new content start */ setTimeout(() => this.cbResolve()) /* new content end */ } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err /* new content start */ setTimeout(() => this.cbReject()) /* new content end */ } then(onResolve, onReject) { this.cbResolve = onResolve this.cbReject = onReject } } const l1 = new LPromise((resolve, reject) => resolve()) l1.then( res => console.log('res'), err => console.log('err') ) ``` 考虑到 微任务 和 宏任务。我们可以使用 MutationObserver 替代 setTimeout ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res /* new content start */ const run = () => this.cbResolve() const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') /* new content end */ } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err /* new content start */ const run = () => this.cbReject() const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') /* new content end */ } then(onResolve, onReject) { this.cbResolve = onResolve this.cbReject = onReject } } const l1 = new LPromise((resolve, reject) => resolve()) l1.then( res => console.log('res'), err => console.log('err') ) ``` ## 4、链式调用 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E9%93%BE%E5%BC%8F%E8%B0%83%E7%94%A8.html) 在原本的 **Promise** 中。我们是可以使用 **then** 链式调用。意味着每个 **then** 都返回一个新的 **Promise**。 因为支持链式。所以我们之前的 `cbResolve` 和 `cbReject` 就不能单单保存一个回调。要改回一个数组,将每一个 **then** 中的回调。都保存到回调队列中。等待调用 **resolve** 或者 **reject** 后才执行所有回调函数。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined /* new content start */ this.cbResolveQueue = [] this.cbRejectQueue = [] /* new content end */ callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res /* new content start */ const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn() } } /* new content end */ const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err /* new content start */ const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn() } } /* new content end */ const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { /* new content start */ return new LPromise((resolve, reject) => { const cbResolve = () => { onResolve && onResolve() resolve() } this.cbResolveQueue.push(cbResolve) const cbReject = () => { onReject && onReject() reject() } this.cbRejectQueue.push(cbReject) }) /* new content end */ } } const l1 = new LPromise((resolve, reject) => resolve()) l1.then( res => console.log('res'), err => console.log('err') ).then( res => console.log('res'), err => console.log('err') ) ``` 此时我们已经完成了链式调用,但是我们会发现,此时如果返回一个新的 **Promise** ,却无法获取 **Promise** 的结果。所以我们得加一些判断条件。我们也会发现,此时此刻我们无法接收到 **res** 或 **err** 的参数。所以我们也要完善一下参数传递问题。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { /* new content start */ cbFn && cbFn(res) /* new content end */ } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { /* new content start */ cbFn && cbFn(err) /* new content end */ } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { /* new content start */ const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } /* new content end */ this.cbResolveQueue.push(cbResolve) /* new content start */ const cbReject = err => { onReject && onReject(err) reject(err) } /* new content end */ this.cbRejectQueue.push(cbReject) }) } } const l1 = new LPromise((resolve, reject) => resolve('我是传入的 resolve 数据')) l1.then( res => { console.log('第一个then的res', res) return new LPromise((resolve, reject) => resolve('返回的Promise')) }, err => console.log('第一个then的err', err) ) .then( res => console.log('第二个then的res', res), err => console.log('第二个then的err', err) ) .then( res => console.log('第三个then的res', res), err => console.log('第三个then的err', err) ) ``` 到现在我们已经实现了 **then** 的链式调用 ## 5、实现 catch 方法 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E5%AE%9E%E7%8E%B0catch%E6%96%B9%E6%B3%95.html) 在调用 `catch` 的时候自动在回调队列中添加一个错误回调函数。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn(res) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn(err) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } this.cbResolveQueue.push(cbResolve) const cbReject = err => { onReject && onReject(err) reject(err) } this.cbRejectQueue.push(cbReject) }) } /* new content start */ catch(err) { this.then(undefined, err) } /* new content end */ } const p1 = new LPromise((resolve, reject) => reject('我是p1的错误信息')) p1.then(res => console.log(res)).catch(err => console.log(err)) ``` ## 6、resolve 和 reject 静态方法 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/Resolve%E5%92%8CReject%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95.html) 这两个静态方法比较简单。只需要返回一个固定状态的 **Promise** 即可。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn(res) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn(err) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } this.cbResolveQueue.push(cbResolve) const cbReject = err => { onReject && onReject(err) reject(err) } this.cbRejectQueue.push(cbReject) }) } /* new content start */ static resolve(res) { return new LPromise(resolve => resolve(res)) } static reject(err) { return new LPromise((undefined, reject) => reject(err)) } /* new content end */ } const p1 = LPromise.resolve('成功') console.log(p1) const p2 = LPromise.reject('失败') console.log(p2) ``` ## 7、实现 finally 方法 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E5%AE%9E%E7%8E%B0finally%E6%96%B9%E6%B3%95.html) 这个与 catch 类似的实现,只需要保证不管成功还是失败都执行里面的回调。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn(res) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn(err) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } this.cbResolveQueue.push(cbResolve) const cbReject = err => { onReject && onReject(err) reject(err) } this.cbRejectQueue.push(cbReject) }) } catch(err) { this.then(undefined, err) } /* new content start */ finally(callback) { this.then(callback, callback) } /* new content end */ static resolve(res) { return new LPromise(resolve => resolve(res)) } static reject(err) { return new LPromise((undefined, reject) => reject(err)) } } const p1 = new LPromise((resolve, reject) => reject('我是p1的错误信息')) p1.then( res => console.log(res), err => console.log(err) ).finally(() => console.log('finally')) ``` ## 8、实现 race 方法 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E5%AE%9E%E7%8E%B0race%E6%96%B9%E6%B3%95.html) **race** 就是返回最先执行成功的结果。不管是成功还是失败。这样我们只需要遍历该 **Promise** ,正常返回数据。谁先执行完成,谁先返回即可。注意要控制状态,防止返回多个结果。 **race** 只需要返回最快的一个结果。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn(res) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn(err) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } this.cbResolveQueue.push(cbResolve) const cbReject = err => { onReject && onReject(err) reject(err) } this.cbRejectQueue.push(cbReject) }) } catch(err) { this.then(undefined, err) } finally(callback) { this.then(callback, callback) } static resolve(res) { return new LPromise(resolve => resolve(res)) } static reject(err) { return new LPromise((undefined, reject) => reject(err)) } /* new content start */ static race(promiseArr) { return new LPromise((resolve, reject) => { let isContinue = true promiseArr.forEach(promise => { promise.then( res => { if (isContinue) { isContinue = false resolve(res) } }, err => { if (isContinue) { isContinue = false reject(err) } } ) }) }) } /* new content end */ } const p1 = new LPromise((resolve, reject) => setTimeout(() => resolve(1), 200)) const p2 = new LPromise((resolve, reject) => setTimeout(() => reject(2), 1000)) const p3 = new LPromise((resolve, reject) => setTimeout(() => resolve(3), 3000)) LPromise.race([p1, p2, p3]).then( res => console.log('res', res), err => console.log('err', err) ) ``` ## 9、实现 all 方法 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E5%AE%9E%E7%8E%B0all%E6%96%B9%E6%B3%95.html) **all** 方法当所有 **Promise** 都成功时返回所有结果的数组,否则返回第一个失败的结果。我们只需要遍历该 **Promise** 数组。定义个变量存放当前 **res** 的长度。如果长度等于数组的长度,我们就 **resolve** 出去。否则发现第一个失败的时候,直接 **reject**。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn(res) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn(err) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } this.cbResolveQueue.push(cbResolve) const cbReject = err => { onReject && onReject(err) reject(err) } this.cbRejectQueue.push(cbReject) }) } catch(err) { this.then(undefined, err) } finally(callback) { this.then(callback, callback) } static resolve(res) { return new LPromise(resolve => resolve(res)) } static reject(err) { return new LPromise((undefined, reject) => reject(err)) } static race(promiseArr) { return new LPromise((resolve, reject) => { let isContinue = true promiseArr.forEach(promise => { promise.then( res => { if (isContinue) { isContinue = false resolve(res) } }, err => { if (isContinue) { isContinue = false reject(err) } } ) }) }) } /* new content start */ static all(promiseArr) { return new LPromise((resolve, reject) => { const resArr = [] const length = promiseArr.length promiseArr.forEach(p => { p.then( res => { resArr.push(res) if (resArr.length === length) { resolve(resArr) } }, err => reject(err) ) }) }) } /* new content end */ } const p1 = new LPromise((resolve, reject) => setTimeout(() => resolve(1), 200)) const p2 = new LPromise((resolve, reject) => setTimeout(() => reject(2), 1000)) const p3 = new LPromise((resolve, reject) => setTimeout(() => reject(3), 3000)) LPromise.all([p1, p2, p3]).then( res => console.log('res', res), err => console.log('err', err) ) ``` ## 10、实现 allSettled 方法 [此处代码,点击这里](https://github.com/Layouwen/blog_demo_lpromise/blob/master/%E5%AE%9E%E7%8E%B0allSettled%E6%96%B9%E6%B3%95.html) 该方法与 **all** 类似。只是这个方法不管成功或失败,只要该 **Promise** 数组执行完毕。就会返回所有结果。我们只需要判断执行过的 **Promise** 长度是否等于数组长度。当一致时就直接 **resolve**。并且每次执行的时候,将返回值以指定格式的对象保存到返回的 **res** 中。 ```js class LPromise { constructor(callbackFn) { this['[[PromiseState]]'] = 'pending' this['[[PromiseResult]]'] = undefined this.cbResolveQueue = [] this.cbRejectQueue = [] callbackFn(this.#resolve.bind(this), this.#reject.bind(this)) } #resolve(res) { this['[[PromiseState]]'] = 'fulfilled' this['[[PromiseResult]]'] = res const run = () => { let cbFn while ((cbFn = this.cbResolveQueue.shift())) { cbFn && cbFn(res) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err const run = () => { let cbFn while ((cbFn = this.cbRejectQueue.shift())) { cbFn && cbFn(err) } } const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } then(onResolve, onReject) { return new LPromise((resolve, reject) => { const cbResolve = res => { const resolveRes = onResolve && onResolve(res) if (resolveRes instanceof LPromise) { resolveRes.then(resolve) } else { resolve(res) } } this.cbResolveQueue.push(cbResolve) const cbReject = err => { onReject && onReject(err) reject(err) } this.cbRejectQueue.push(cbReject) }) } catch(err) { this.then(undefined, err) } finally(callback) { this.then(callback, callback) } static resolve(res) { return new LPromise(resolve => resolve(res)) } static reject(err) { return new LPromise((undefined, reject) => reject(err)) } static race(promiseArr) { return new LPromise((resolve, reject) => { let isContinue = true promiseArr.forEach(promise => { promise.then( res => { if (isContinue) { isContinue = false resolve(res) } }, err => { if (isContinue) { isContinue = false reject(err) } } ) }) }) } static all(promiseArr) { return new LPromise((resolve, reject) => { const resArr = [] const length = promiseArr.length promiseArr.forEach(p => { p.then( res => { resArr.push(res) if (resArr.length === length) { resolve(resArr) } }, err => reject(err) ) }) }) } /* new content start */ static allSettled(promiseArr) { return new LPromise(resolve => { const resArr = new Array(promiseArr.length) let num = 0 promiseArr.forEach(p => { let obj = {} p.then( res => { obj.status = 'fulfilled' obj.value = res resArr[num] = obj num++ if (num === resArr.length) resolve(resArr) }, err => { obj.status = 'rejected' obj.reason = err resArr[num] = obj num++ if (num === resArr.length) resolve(resArr) } ) }) }) } /* new content end */ } const p1 = new LPromise((resolve, reject) => setTimeout(() => resolve(1), 200)) const p2 = new LPromise((resolve, reject) => setTimeout(() => reject(2), 1000)) const p3 = new LPromise((resolve, reject) => setTimeout(() => reject(3), 3000)) LPromise.allSettled([p1, p2, p3]).then( res => console.log('res', res), err => console.log('err', err) ) ``` ## End 本文章实现的 Promise 不够完善,只是大概把实现原理带大家过一遍。Promise 的源码不是由 js 写的,所以我们只能尽可能使用 js 模仿。欢淫各位大佬补充更完善的版本。 交流学习~ > 微信:gdgzyw > github: [www.github.com/layouwen](www.github.com/layouwen)