Promise模拟实现

简介

Promise基本知识参考:Promise小结

简易版

function MyPromise(executor) { if (typeof executor !== 'function') { throw new TypeError('this is not a function') } this.cbs = [] const resolve = value => { this.value = value this.cbs.forEach(v => v()) } executor(resolve) } MyPromise.prototype.then = function(onResolved) { typeof onResolved !== 'function' && (onResolved = v => v) return new MyPromise(resolve => { this.cbs.push(() => { const res = onResolved(this.value) if (res instanceof MyPromise) { res.then(resolve) } else { resolve(res) } }) }) } // 测试 new MyPromise(resolve => { console.log('promise') setTimeout(() => { resolve('resolve') }, 1000) }).then(res => { console.log(res) return new MyPromise((resolve) => { setTimeout(() => { resolve(1) }, 500) }) }).then(res => { console.log(2, res) })

完整版

const PromiseTypes = { PENDING: 'pending', FULFILLED: 'fulfilled', REJECTED: 'rejected' } function MyPromise(executor) { if (typeof executor !== 'function') throw new TypeError('this is not a function') this.status = PromiseTypes.PENDING this.value = undefined this.reason = undefined this.onResolvedCallbacks = [] this.onRejectedCallbacks = [] const resolve = value => { if (this.status === PromiseTypes.PENDING) { this.value = value this.status = PromiseTypes.FULFILLED this.onResolvedCallbacks.forEach(v => v()) } } const reject = reason => { if (this.status === PromiseTypes.PENDING) { this.reason = reason this.status = PromiseTypes.REJECTED this.onRejectedCallbacks.forEach(v => v()) } } try { executor(resolve, reject) } catch(e) { console.log('executor, error') reject(e) } } MyPromise.prototype.then = function(onFulfilled, onRejected) { let promise2 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r } if (this.status === PromiseTypes.FULFILLED) { promise2 = new MyPromise((resolve, reject) => { // onFulfilled(this.value) 要放在try...catch中执行,捕获异常 asyncCallback(promise2, () => onFulfilled(this.value), resolve, reject) }) } if (this.status === PromiseTypes.REJECTED) { promise2 = new MyPromise((resolve, reject) => { asyncCallback(promise2, () => onRejected(this.reason), resolve, reject) }) } if (this.status === PromiseTypes.PENDING) { promise2 = new MyPromise((resolve, reject) => { this.onResolvedCallbacks.push(() => { asyncCallback(promise2, () => onFulfilled(this.value), resolve, reject) }) this.onRejectedCallbacks.push(() => { asyncCallback(promise2, () => onRejected(this.reason), resolve, reject) }) }) } return promise2 } function asyncCallback(promise2, cb, resolve, reject) { setTimeout(() => { try { const x = cb() resolvePromise(promise2, x, resolve, reject) } catch(e) { reject(e) } }, 0) } function resolvePromise(promise2, x, resolve, reject) { if (x === promise2) { return reject(new TypeError('Chaining cycle detected for promise')) } if (x instanceof MyPromise) { if (x.status === PromiseTypes.PENDING) { x.then(v => { resolvePromise(promise2, v, resolve, reject) }, reject) } else { x.then(resolve, reject) } return } let called = false if (x !== null && (typeof x === 'object' || typeof 'x' === 'function')) { try { let then = x.then if (typeof then === 'function') { then.call(x, y => { if (called) return called = true return resolvePromise(promise2, y, resolve, reject) }, err => { if (called) return called = true return reject(err) }) } else { resolve(x) } } catch(e) { if (called) return called = true return reject(e) } } else { resolve(x) } } // 测试 new MyPromise((resolve, reject) => { console.log('promise') setTimeout(() => { resolve('resolve') }, 1000) }).then(res => { console.log(res) return new MyPromise((resolve, reject) => { setTimeout(() => { resolve(1) }, 500) }) }).then(res => { console.log(2, res) })

参考:剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类

Promise.prototype.catch

MyPromise.prototype.catch = function(fn) { this.then(null, fn) }

Promise.prototype.finally

MyPromise.prototype.finally = function(callback) { const P = this.constructor return this.then( value => P.resolve(callback()).then(() => value), reason => P.resolve(callback()).then(() => { throw reason }) ) }

Promise.resolve

MyPromise.resolve = function(val) { return new MyPromise((resolve, reject) => { resolve(val) }) }

Promise.reject

MyPromise.reject = function(err) { return new MyPromise((resolve, reject) => { reject(err) }) }

Promise.race

Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,
不管结果本身是成功状态还是失败状态

MyPromise.race = function(arr) { return new MyPromise((resolve, reject) => { arr.forEach(item => { if (item instanceof MyPromise) { // 处理Promise对象 item.then(resolve, reject) } else { // 处理非Promise对象 MyPromise.resolve(item).then(resolve, reject) } }) }) } // 测试 const p1 = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(11) }, 2000) }) const p2 = new MyPromise((resolve, reject) => { reject('asfs') }); const p3 = new MyPromise((resolve) => { setTimeout(() => { resolve(33) }, 4) }); MyPromise.race([p1, p3, 3, 4]).then(data => { console.log(data) }, err => { console.log('失败跑的最快') }) MyPromise.race([p1, p2, p3, 3, 4]).then(data => { console.log(data) }, err => { console.log('失败跑的最快') })

Promise.all

获取所有的promise,都执行then,把结果放到数组,一起返回
如果出现异常,立即返回异常

MyPromise.all = function(arr) { return new MyPromise((resolve, reject) => { if (arr.length === 0) { resolve([]) return } const resArr = [] let count = 0 function processData(index, value) { resArr[index] = value count++ if (count === arr.length) { resolve(resArr) } } arr.forEach((item, index) => { if (item instanceof MyPromise) { item.then(value => { processData(index, value) }, reject) } else { processData(index, item) } }) }) } // 测试 const p1 = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(11) }, 2000) }) const p3 = new MyPromise((resolve) => { setTimeout(() => { resolve(33) }, 4) }) MyPromise.all([p1, p3, 3, 4]).then(data => { // 按传入数组的顺序打印 console.log(data) // [ 11, 33, 3, 4 ] }, err => { console.log(err) })

Promise.allSettled

获取所有的promise,都执行then,把结果放到数组,一起返回

Promise.all的区别:

  • Promise.all是这几个Promise有个异常的话,立即返回,返回异常
  • allSettled是等所有的都执行完,再返回。整个过程不会有异常。每个返回的结果中,会有这个Promise的状态(成功返回还是异常)和返回值(成功的返回值或者原因)
MyPromise.allSettled = function(arr) { return new MyPromise((resolve, reject) => { const len = arr.length const resArr = new Array(len) let count = 0 function processData(index, data) { resArr[index] = data count++ if (count === len) { resolve(resArr) } } res.forEach((item, index) => { if (item instanceof MyPromise) { item.then(value => { processData(index, { status: 'fulfilled', value }) }, reason => { processData(index, { status: 'rejected', reason }) }) } else { processData(index, { status: 'fulfilled', value: item }) } }) }) }

创作不易,若本文对你有帮助,欢迎打赏支持作者!

 分享给好友: