1、前言
本篇文章,默认你已经知道什么是 Promise ,然后我会带你一步步的实现一个简易的 Promise。将会以循序渐进的方式,分步骤实现。
本文章相关代码地址:https://github.com/layouwen/blog_demo_lpromise
如果本文章对你有所帮助,请不要吝啬你的 Start 哦~
2、三种状态
此处代码,点击这里
Promise 它一共会有三种状态:
- pending
- fulfilled
- rejected
下面我们自己实现一个类,默认为 pending 状态,通过调用 resolve 或者 reject 改变其状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 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'))) const l1 = new LPromise((resolve, reject) => { resolve('我调用了resolve') }) console.log(l1) const l2 = new LPromise((resolve, reject) => { reject('我调用了reject') }) console.log(l2)
|
3、实现 then 参数回调
此处代码,点击这里
返回的 Promise ,可以通过使用 then 传递成功和失败的回调。
通过 then 接收了两个回调。实现了分别调用回调的内容。但是发现,他们两个都会执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 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 } then(onResolve, onReject) { onResolve() onReject() } } const l1 = new LPromise((resolve, reject) => resolve()) l1.then( res => console.log('res'), err => console.log('err') )
|
对执行时机进行调整。使其在调用 resolve 或 reject 才执行相关的回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 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 this.cbResolve() } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err this.cbReject() } 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') )
|
改装后,发现 resolve 和 reject 的执行时间比 then 的回调要快。导致无法执行 then 中的回调。我们需要对 resolve 和 reject 中执行回调的部分进行 延迟执行。可以使用 setTimeout 进行延迟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 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 setTimeout(() => this.cbResolve()) } #reject(err) { this['[[PromiseState]]'] = 'reject' this['[[PromiseResult]]'] = err setTimeout(() => this.cbReject()) } 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 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 const run = () => this.cbResolve() 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 = () => this.cbReject() const ob = new MutationObserver(run) ob.observe(document.body, { attributes: true }) document.body.setAttribute('lpromise', 'layouwen') } 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、链式调用
此处代码,点击这里
在原本的 Promise 中。我们是可以使用 then 链式调用。意味着每个 then 都返回一个新的 Promise。
因为支持链式。所以我们之前的 cbResolve
和 cbReject
就不能单单保存一个回调。要改回一个数组,将每一个 then 中的回调。都保存到回调队列中。等待调用 resolve 或者 reject 后才执行所有回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| 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() } } 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() } } 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 = () => { onResolve && onResolve() resolve() } this.cbResolveQueue.push(cbResolve) const cbReject = () => { onReject && onReject() reject() } this.cbRejectQueue.push(cbReject) }) } } 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 的参数。所以我们也要完善一下参数传递问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| 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) }) } } 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 方法
此处代码,点击这里
在调用 catch
的时候自动在回调队列中添加一个错误回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 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) } } const p1 = new LPromise((resolve, reject) => reject('我是p1的错误信息')) p1.then(res => console.log(res)).catch(err => console.log(err))
|
6、resolve 和 reject 静态方法
此处代码,点击这里
这两个静态方法比较简单。只需要返回一个固定状态的 Promise 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| 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) }) } static resolve(res) { return new LPromise(resolve => resolve(res)) } static reject(err) { return new LPromise((undefined, reject) => reject(err)) } } const p1 = LPromise.resolve('成功') console.log(p1) const p2 = LPromise.reject('失败') console.log(p2)
|
7、实现 finally 方法
此处代码,点击这里
这个与 catch 类似的实现,只需要保证不管成功还是失败都执行里面的回调。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| 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)) } } const p1 = new LPromise((resolve, reject) => reject('我是p1的错误信息')) p1.then( res => console.log(res), err => console.log(err) ).finally(() => console.log('finally'))
|
8、实现 race 方法
此处代码,点击这里
race 就是返回最先执行成功的结果。不管是成功还是失败。这样我们只需要遍历该 Promise ,正常返回数据。谁先执行完成,谁先返回即可。注意要控制状态,防止返回多个结果。 race 只需要返回最快的一个结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| 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) } } ) }) }) } } 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 方法
此处代码,点击这里
all 方法当所有 Promise 都成功时返回所有结果的数组,否则返回第一个失败的结果。我们只需要遍历该 Promise 数组。定义个变量存放当前 res 的长度。如果长度等于数组的长度,我们就 resolve 出去。否则发现第一个失败的时候,直接 reject。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| 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) ) }) }) } } 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 方法
此处代码,点击这里
该方法与 all 类似。只是这个方法不管成功或失败,只要该 Promise 数组执行完毕。就会返回所有结果。我们只需要判断执行过的 Promise 长度是否等于数组长度。当一致时就直接 resolve。并且每次执行的时候,将返回值以指定格式的对象保存到返回的 res 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
| 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) ) }) }) } 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) } ) }) }) } } 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