原文: 本人掘金文章
关注公众号: 微信搜索 web全栈进阶
; 收货更多的干货
一、Es5语法
function MyPromise (executor) {
this.state = 'pending'
// 成功的值
this.data = undefined
// 失败的原因
this.reason = undefined
this.callbacks = []
// 成功回调, state 重置为 resolved
let resolve = (value) => {
if (this.state !== 'pending') return
this.state = 'resolved'
this.data = value
// 立即执行异步回调函数
setTimeout(_ => {
this.callbacks.forEach(callback => {
callback.onResolved(value)
})
})
}
// 失败回调, state 重置为 rejected
let reject = (reason) => {
if (this.state !== 'pending') return
this.state = 'rejected'
this.reason = reason
setTimeout(_ => {
this.callbacks.forEach(callback => {
callback.onRejected(reason)
})
})
}
// 如果executor执行报错,直接执行reject
try{
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
// Promise原型链上的then方法,可以接收两个参数(且是回调函数),成功/失败,并且每次返回的都是一个新的Promise
MyPromise.prototype.then = function (onResolved, onRejected) {
let _this = this
onResolved = typeof onResolved === 'function' ? onResolved : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => console.error(reason)
// promise对象当前状态为pending
// 此时并不能确定调用onResolved还是onRejected,需要等待promise的状态改变
return new MyPromise((resolve, reject) => {
/*
* 1、返回的Promise的结果是由onResolved/onrejected决定的
* 2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
* 3、返回的不是Promise对象 (该值就是Promise的返回结果)
* 4、抛出异常 异常的值为返回的结果
*/
// 统一处理函数
function handle (callback) {
try {
const result = callback(_this.data)
if (reject instanceof MyPromise) {
result.then(value => {
resolve(value)
}, reason => {
reject(reason)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
if (_this.state === 'resolved') {
setTimeout(_ => {
handle(onResolved)
})
}
if (_this.state === 'rejected') {
setTimeout(_ => {
handle(onRejected)
})
}
if (_this.state === 'pending') {
_this.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onResolved)
}
})
}
})
}
// 错误捕获
MyPromise.prototype.catch = function (onRejected) {
return this.then(null, onRejected)
}
MyPromise.resolve = function (value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
MyPromise.reject = function (reason) {
console.log(reason)
return new MyPromise((resolve, reject) => reject(reason)) // 返回一个reject状态Promise对象
}
/*
* Promise.all可以将多个Promise实例包装成一个新的Promise实例。
* 同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值
*/
MyPromise.all = function (promises) {
if (typeof promises !== 'object' || promises.constructor !== Array) return console.error('参数需为数组!')
let count = 0
let values = new Array(promises.length)
return new MyPromise((resolve,reject) => {
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(value => {
count++
values[index] = value
if (count === promises.length) resolve(values)
}, error => {
reject(error)
})
})
})
}
/*
* Promise.race 返回数组实例中最先改变状态的实例(无论成功还是失败)
*
*/
MyPromise.race = function (promises) {
return new MyPromise((resolve,reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(value => {
resolve(value)
}, error => {
reject(error)
})
})
})
}
二、Es6 class 语法
class _Promise {
constructor (executor) {
const _this = this
this.state = 'pending'
// 成功的值
this.data = undefined
// 失败的原因
this.reason = undefined
this.callbacks = []
function resolve (value) {
if (_this.state === 'pending') return
_this.state = 'resolved'
_this.data = value
setTimeout(_ => {
_this.callbacks.forEach(callback => {
callback.onResolved(value)
})
})
}
function reject (reason) {
if (_this.state === 'pending') return
_this.state = 'rejected'
_this.reason = reason
setTimeout(_ => {
_this.callbacks.forEach(callback => {
callback.onRejected(reason)
})
})
}
executor(resolve, reject)
}
then(onResolved, onRejected) {
const _this = this
onResolved = typeof onResolved === 'function' ? onResolved : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => console.error(reason)
return new _Promise((resolve, reject) => {
function handle (callback) {
try {
const result = callback(_this.data)
if (reject instanceof _Promise) {
result.then(value => {
resolve(value)
}, reason => {
reject(reason)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
if (_this.state === 'resolved') {
setTimeout(_ => {
handle(onResolved)
})
}
if (_this.state === 'rejected') {
setTimeout(_ => {
handle(onRejected)
})
}
if (_this.state === 'pending') {
_this.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onResolved)
}
})
}
})
}
catch (onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
if (value instanceof _Promise) return value;
return new _Promise(resolve => resolve(value)) // 返回一个resolved状态的新Promise对象
}
static reject(reason) {
return new _Promise((resolve, reject) => reject(reason)); // 返回一个reject状态新Promise对象
}
static all(promises) {
let count = 0
let values = new Array(promises.length)
return new _Promise((resolve, reject) => {
promises.forEach((promise, index) => {
_Promise.resolve(promise).then(value => {
count++
values[index] = value
if (count === promises.length) resolve(values)
}, reason => reject(reason))
})
})
}
static race(promises) {
return new _Promise((resolve, reject) => {
promises.forEach(promise => {
_Promise.resolve(promise).then(value => resolve(value))
}, reason => reject(reason))
})
}
}
三、测试
/* 测试 */
window.onload = function () {
f3()
let p1 = new MyPromise((resolve,reject) => {
resolve('p1 执行完毕')
})
let p2 = new MyPromise((resolve,reject) => {
resolve('p2执行完毕')
})
let p3 = MyPromise.reject('失败')
MyPromise.all([p1, p2]).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})
MyPromise.race([p1, p2, p3]).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})
}
function f1 () {
return new _Promise((resolve,reject) => {
f4()
resolve(1)
})
}
function f2 () {
console.log('f2f2f2f2f2f2f2f2')
}
function f4 () {
console.log('f4f4f4f4f4f4f4f4')
}
function f3 () {
let p = f1()
p.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
f2()
}
// 测试结果
// f4f4f4f4f4f4f4f4
// f2f2f2f2f2f2f2f2
// 失败
// ["p1 执行完毕", "p2执行完毕"]
// p1 执行完毕