js在进行异步操做时,常常会使用promise来获取异步操做的返回结果,那promise内部到底是如何实现的?api
本文经过手写一个符合promise A+规范的promise类,来深刻了解promise的实现逻辑。数组
promise A+规范,是一个开源的、可被开发者实现的标准promise规范,规定了实现一个标准的promise具体须要实现哪些功能。promise
具体实现功能细则参考:promises A+规范浏览器
大概分为两种:异步
Promise.all, Promise.resolve, Promise.reject, Promise.race函数
then/catch/finally测试
let promise = new Promise(function(resolve, reject) {
// 若是作什么异步操做成功了
setTimeout(() => {
let isSuccess = true
if (isSuccess) {
resolve('接口返回成功了')
} else {
reject('接口返回失败了')
}
}, 1000)
})
promise.then(value => {
console.log('success', value)
}, error => {
console.log('error', error)
})
// 日志打印
// -> 接口返回成功了
复制代码
如何实现一个promiseui
能够看到promise是一个类,里面传递一个带了resolve和reject参数的函数,这个函数叫作executor执行器,executor中包含了一个resolve函数和一个reject函数。this
具体实现:spa
// 定义promise的三种状态常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
// 初始化promise状态和value值
let that = this
that.status = PENDING
that.value = undefined
// resolve执行时,将状态置为成功态
function resolve(value) {
// 只有状态为pending时,status修改成fulfilled,同时更新value的值
if (that.status === PENDING) {
that.status = FULFILLED
that.value = value
}
}
// reject执行时,将状态置为失败态
function reject(reason) {
if (that.status === PENDING) {
that.status = REJECTED
that.value = reason
}
}
executor(resolve, reject)
}
Promise.prototype.then = function(onFulfilled, onRejected) {
let that = this
// 若是当前状态为已完成,则执行完成的回调
if (that.status === FULFILLED) {
onFulfilled(that.value)
}
// 若是当前状态为已失败,则执行失败的回调
if (that.status === REJECTED) {
onRejected(that.value)
}
}
复制代码
一个简单的promise实现就已经完成,包含new Promise(executor: (resolve, reject) => void)的实现,而且支持then调用的逻辑来获取value或者reason。
可是该实现还不支持异步resolve或者reject状态
前面实现的promise,还有一个问题,就是executor执行器里的resolve若是延迟执行,好比延迟1000ms后再执行,当promise.then优先于resolve或者reject执行,此时该promise的status仍是pending状态,不会执行then里面的onFulfilled和onRejected方法
因此这里咱们要使用发布/订阅者模式,将promise.then里面的onFulfilled和onRejected两个监听方法存储起来,在promise的状态resolve或者reject时再通知对应的监听方法
添加发布/订阅者模式
// 定义promise的三种状态常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
// 初始化promise状态和value值
let that = this
that.status = PENDING
that.value = undefined
// 初始化订阅resolve和rejecte方法的回调数组
that.onFulfilledCallbacks = []
that.onRejectedCallbacks = []
// resolve执行时,将状态置为成功态
function resolve(value) {
// 只有状态为pending时,status修改成fulfilled,同时更新value的值
if (that.status === PENDING) {
that.status = FULFILLED
that.value = value
// 执行订阅了resolve的回调方法
that.onFulfilledCallbacks.forEach(onFulfilled => onFulfilled(that.value))
}
}
// reject执行时,将状态置为失败态
function reject(reason) {
if (that.status === PENDING) {
that.status = REJECTED
that.value = reason
// 执行订阅了reject的回调方法
that.onRejectedCallbacks.forEach(onRejected => onRejected(that.value))
}
}
executor(resolve, reject)
}
Promise.prototype.then = function(onFulfilled, onRejected) {
let that = this
// 若是当前状态为已完成,则执行完成的回调
if (that.status === FULFILLED) {
onFulfilled(that.value)
}
// 若是当前状态为已失败,则执行失败的回调
if (that.status === REJECTED) {
onRejected(that.value)
}
// 若是当前状态还在pending,则将回调方法添加到订阅状态的回调中
if (that.status === PENDING) {
// 订阅resolve的回调
that.onFulfilledCallbacks.push(onFulfilled)
// 订阅reject的回调
that.onRejectedCallbacks.push(onRejected)
}
}
复制代码
好的,如今咱们实现的promise已经很是强大了,能够写一个简单的测试用例,跑一下。
let promise1 = new Promise(function(resolve, reject) {
resolve('promise1-直接返回成功')
})
let promise2 = new Promise(function(resolve, reject) {
setTimeout(() => {
reject('promise2-异步返回成功')
}, 1000)
})
let promise3 = new Promise(function(resolve, reject) {
resolve('promise3-直接返回成功')
reject('promise3-直接返回失败')
})
promise1.then((value) => {
console.log('promise1-执行了onFulfilled', value)
}, (reason) => {
console.log('promise1-执行了onRejected', reason)
})
promise2.then((value) => {
console.log('promise2-执行了onFulfilled', value)
}, (reason) => {
console.log('promise2-执行了onRejected', reason)
})
promise3.then((value) => {
console.log('promise3-执行了onFulfilled', value)
}, (reason) => {
console.log('promise3-执行了onRejected', reason)
})
// 执行结果
// -> promise1-执行了onFulfilled promise1-接口返回成功了
// -> promise3-执行了onFulfilled promise3-接口返回成功了
// 1000ms后
// -> promise2-执行了onRejected promise2-异步返回成功
复制代码
测试结果符合要求
promise1经过resolve,直接触发then里的onFulfilled,打印promise1-执行了onFulfilled promise1-接口返回成功了
promise2经过延迟触发reject,延迟1000ms后触发了onRejected,打印promise2-执行了onRejected
promise3先resolve再reject,因为resolve后当前promise状态会更新为fulfilled,因此后面再执行reject会无效,直接打印promise3-执行了onFulfilled
目前咱们的promise实现了如下功能:
这就是一个简单的符合promise A+规范promise实现,不过promise还有许多其余的功能特性和api,好比:Promise.resolve,Promise.reject,Promise.all等,我会在后面的文章中更新。
未完待续...