Promise/A+: www.ituring.com.cn/article/665…
Promise: github.com/then/promis…
asap: github.com/kriskowal/a…
首先看下原生Promise的用法
// 把下面代码放到控制台查看结果
new Promise((resolve,reject)=>{
}) // pending---undefined
// 把下面代码放到控制台查看结果
new Promise((resolve,reject)=>{
resolve(1)
}) // fulfilled---1
// 把下面代码放到控制台查看结果
new Promise((resolve,reject)=>{
reject(2)
}) // rejected---2
使用class写法
基础3步
class MyPromise {
/**
* 1,由于Promise是一个构造函数,所以需要实现constructor函数
* 2,constructor函数接受一个回调函数executor,并且是同步执行的
* 3,executor函数需要2个参数,
* 一个是执行成功的resolve参数,
* 一个是执行失败的reject参数,这2个参数都是函数,
* 由于是在构造函数里执行的executor函数,
* 所以resolve和reject这2个函数参数需要在这里定义,
* 并传递给executor函数执行
*/
constructor(executor){
function resolve(value){
}
function reject(reason){
}
executor(resolve, reject)
}
}
第4步,实现resolve和reject函数
// 定义Promise的3种状态
const PENDING = "pending"
const FULFILLED = "fulfilled"
const REJECTED = "rejected"
class MyPromise {
// 初始状态为pending
#PromiseState = PENDING
#PromiseResult = undefined
/**
* 1,由于Promise是一个构造函数,所以需要实现constructor函数
* 2,constructor函数接受一个回调函数executor,并且是同步执行的
* 3,executor函数需要2个参数,
* 一个是执行成功的resolve参数,
* 一个是执行失败的reject参数,
* 这2个参数都是函数,由于是在构造函数里执行的executor函数,
* 所以resolve和reject这2个函数参数需要在这里定义,并传递给executor函数执行
* 4,resolve和reject函数是Promise提供的,而调用需要使用者主动调用的,
* 当使用者需要执行的代码段执行成功时,使用者需要调用resolve函数,
* 告诉Promise代码已经执行成功,并把执行结果传递给resolve函数,
* 因此resolve函数里需要(改变Promise状态+存储结果),
* 因此Promise需要2个属性PromiseState和PromiseResult用来保存数据
*/
constructor(executor){
function resolve(value){
this.#PromiseState = FULFILLED
this.#PromiseResult = value
}
function reject(reason){
this.#PromiseState = REJECTED
this.#PromiseResult = reason
}
executor(resolve, reject)
}
}
第5步,resolve和reject需要一点点限制
// 定义Promise的3种状态
const PENDING = "pending"
const FULFILLED = "fulfilled"
const REJECTED = "rejected"
class MyPromise {
// 初始状态为pending
#PromiseState = PENDING
#PromiseResult = undefined
/**
* 1,由于Promise是一个构造函数,所以需要实现constructor函数
* 2,constructor函数接受一个回调函数executor,并且是同步执行的
* 3,executor函数需要2个参数,
* 一个是执行成功的resolve参数,
* 一个是执行失败的reject参数,
* 这2个参数都是函数,由于是在构造函数里执行的executor函数,
* 所以resolve和reject这2个函数参数需要在这里定义,并传递给executor函数执行
* 4,resolve和reject函数是Promise提供的,而调用需要使用者主动调用的,
* 当使用者需要执行的代码段执行成功时,使用者需要调用resolve函数,
* 告诉Promise代码已经执行成功,并把执行结果传递给resolve函数,
* 因此resolve函数里需要(改变Promise状态+存储结果),
* 因此Promise需要2个属性PromiseState和PromiseResult用来保存数据
*
* 5,由于Promise的状态只能从pending变为fulfilled,
* 或者从pending变为rejected,因此resolve和reject函数中需要加上限制,如下
*/
constructor(executor){
function resolve(value){
if(this.#PromiseState !== PENDING) return // 第5点的限制
this.#PromiseState = FULFILLED
this.#PromiseResult = value
}
function reject(reason){
if(this.#PromiseState !== PENDING) return // 第5点的限制
this.#PromiseState = REJECTED
this.#PromiseResult = reason
}
executor(resolve, reject)
}
}
简单优化下代码
resolve和reject代码相似,抽离
// 定义Promise的3种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// 初始状态为pending
#PromiseState = PENDING
#PromiseResult = undefined
/**
* 1,由于Promise是一个构造函数,所以需要实现constructor函数
* 2,constructor函数接受一个回调函数executor,并且是同步执行的
* 3,executor函数需要2个参数,
* 一个是执行成功的resolve参数,
* 一个是执行失败的reject参数,
* 这2个参数都是函数,由于是在构造函数里执行的executor函数,
* 所以resolve和reject这2个函数参数需要在这里定义,并传递给executor函数执行
* 4,resolve和reject函数是Promise提供的,而调用需要使用者主动调用的,
* 当使用者需要执行的代码段执行成功时,使用者需要调用resolve函数,
* 告诉Promise代码已经执行成功,并把执行结果传递给resolve函数,
* 因此resolve函数里需要(改变Promise状态+存储结果),
* 因此Promise需要2个属性PromiseState和PromiseResult用来保存数据
*
* 5,由于Promise的状态只能从pending变为fulfilled,
* 或者从pending变为rejected,因此resolve和reject函数中需要加上限制,如下
*/
constructor(executor) {
function resolve(value) {
this.#changeState(FULFILLED, value)
}
function reject(reason) {
this.#changeState(REJECTED, reason)
}
executor(resolve, reject)
}
#changeState(state, result) {
if (this.#PromiseState !== PENDING) return // 第5点的限制
this.#PromiseState = state
this.#PromiseResult = result
}
}
第6步,实现then方法
// 定义Promise的3种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// 初始状态为pending
#PromiseState = PENDING
#PromiseResult = undefined
#handlers = []
/**
* 1,由于Promise是一个构造函数,所以需要实现constructor函数
* 2,constructor函数接受一个回调函数executor,并且是同步执行的
* 3,executor函数需要2个参数,
* 一个是执行成功的resolve参数,
* 一个是执行失败的reject参数,
* 这2个参数都是函数,由于是在构造函数里执行的executor函数,
* 所以resolve和reject这2个函数参数需要在这里定义,并传递给executor函数执行
* 4,resolve和reject函数是Promise提供的,而调用需要使用者主动调用的,
* 当使用者需要执行的代码段执行成功时,使用者需要调用resolve函数,
* 告诉Promise代码已经执行成功,并把执行结果传递给resolve函数,
* 因此resolve函数里需要(改变Promise状态+存储结果),
* 因此Promise需要2个属性PromiseState和PromiseResult用来保存数据
*
* 5,由于Promise的状态只能从pending变为fulfilled,
* 或者从pending变为rejected,因此resolve和reject函数中需要加上限制,如下
*
* 6,实现then方法
* then方法是Promise的实例方法,
* then方法的返回值是Promise,因此直接写 return new MyPromise
* 并且接受2个函数参数,onFulfilled和onRejected,
* 这2个函数参数就是回调函数,当用户的代码块执行成功或失败会被调用
* 调用onFulfilled还是onRejected,需要判断状态PromiseState
* 调用的时候需要把resolve函数执行保存的结果传递到参数中
*
* 如果代码是异步执行的,PromiseState是PENDING的话
* 就需要当用户主动resolve或reject的时候执行,代码要走到resolve或reject函数中,
* resolve或reject函数需要拿到onFulfilled和onRejected函数参数,
* 因此需要把onFulfilled和onRejected保存起来,handlers
* 保存成功后,进入resolve或reject函数去调用,代码写到changeState中吧
*
* 那么then返回的Promise的resolve, reject函数参数什么时候执行,并且参数又是什么
* 其实就是onFulfilled和onRejected执行后执行,参数是onFulfilled和onRejected的执行结果
*
*/
constructor(executor) {
let resolve = (value) => {
this.#changeState(FULFILLED, value)
}
let reject = (reason) => {
this.#changeState(REJECTED, reason)
}
executor(resolve, reject)
}
#changeState(state, result) {
if (this.#PromiseState !== PENDING) return // 第5点的限制
this.#PromiseState = state
this.#PromiseResult = result
this.#execCallback()
}
#execCallback() {
if (this.#PromiseState === PENDING) return
let callback = this.#PromiseState == FULFILLED ? 'onFulfilled' : 'onRejected'
while (this.#handlers.length) {
let handler = this.#handlers.shift()
// 无论第一个then是否成功还是失败,都走第二个then的成功,
// 什么时候走第二个then的失败呢,try...catch
try {
let result = handler[callback](this.#PromiseResult)
handler.resolve(result)
} catch (error) {
handler.reject(error)
}
}
}
// onFulfilled, onRejected什么时候执行
// resolve, reject什么时候执行
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject,
})
this.#execCallback()
})
}
}
终版
- executor必须为函数
- then的onFulfilled或onRejected为null时,直接到下一个then
- Promise.then里面的代码是异步执行的,把runThenCode放到微任务执行,
- 微任务看这里:juejin.cn/editor/draf…
// 定义Promise的3种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function isFun(fn) {
return typeof fn === 'function'
}
class MyPromise {
// 初始状态为pending
#PromiseState = PENDING
#PromiseResult = undefined
#handlers = []
/**
* 1,由于Promise是一个构造函数,所以需要实现constructor函数
* 2,constructor函数接受一个回调函数executor,并且是同步执行的
* 3,executor函数需要2个参数,
* 一个是执行成功的resolve参数,
* 一个是执行失败的reject参数,
* 这2个参数都是函数,由于是在构造函数里执行的executor函数,
* 所以resolve和reject这2个函数参数需要在这里定义,并传递给executor函数执行
* 4,resolve和reject函数是Promise提供的,而调用需要使用者主动调用的,
* 当使用者需要执行的代码段执行成功时,使用者需要调用resolve函数,
* 告诉Promise代码已经执行成功,并把执行结果传递给resolve函数,
* 因此resolve函数里需要(改变Promise状态+存储结果),
* 因此Promise需要2个属性PromiseState和PromiseResult用来保存数据
*
* 5,由于Promise的状态只能从pending变为fulfilled,
* 或者从pending变为rejected,因此resolve和reject函数中需要加上限制,如下
*
* 6,实现then方法
* then方法是Promise的实例方法,
* then方法的返回值是Promise,因此直接写 return new MyPromise
* 并且接受2个函数参数,onFulfilled和onRejected,
* 这2个函数参数就是回调函数,当用户的代码块执行成功或失败会被调用
* 调用onFulfilled还是onRejected,需要判断状态PromiseState
* 调用的时候需要把resolve函数执行保存的结果传递到参数中
*
* 如果代码是异步执行的,PromiseState是PENDING的话
* 就需要当用户主动resolve或reject的时候执行,代码要走到resolve或reject函数中,
* resolve或reject函数需要拿到onFulfilled和onRejected函数参数,
* 因此需要把onFulfilled和onRejected保存起来,handlers
* 保存成功后,进入resolve或reject函数去调用,代码写到changeState中吧
*
* 那么then返回的Promise的resolve, reject函数参数什么时候执行,并且参数又是什么
* 其实就是onFulfilled和onRejected执行后执行,参数是onFulfilled和onRejected的执行结果
*
*/
constructor(executor) {
if (!isFun(executor)) {
throw TypeError('MyPromise resolver undefined is not a function')
}
let resolve = (value) => {
this.#changeState(FULFILLED, value)
}
let reject = (reason) => {
this.#changeState(REJECTED, reason)
}
executor(resolve, reject)
}
#changeState(state, result) {
if (this.#PromiseState !== PENDING) return // 第5点的限制
this.#PromiseState = state
this.#PromiseResult = result
this.#execCallback()
}
#execCallback() {
if (this.#PromiseState === PENDING) return
while (this.#handlers.length) {
let {onFulfilled, onRejected, resolve,reject} = this.#handlers.shift()
// 无论第一个then是否成功还是失败,都走第二个then的成功,
// 什么时候走第二个then的失败呢,try...catch
try {
if (this.#PromiseState === FULFILLED) {
this.#runThenCode(onFulfilled,resolve,reject)
// if (!isFun(onFulfilled)) {
// resolve(this.#PromiseResult)
// }
} else {
this.#runThenCode(onRejected,resolve,reject)
// if (!isFun(onRejected)) {
// reject(this.#PromiseResult)
// }
}
} catch (error) {
reject(error)
}
}
}
#runThenCode(callback, resolve,reject){
// 如果是函数,正常执行
if(isFun(callback)){
let result = callback(this.#PromiseResult)
resolve(result)
}else if(this.#PromiseState === FULFILLED){ // 如果不是函数,但是执行成功,直接到下一个then的onFulfilled
resolve(this.#PromiseResult)
}else{ // 如果不是函数,并且执行失败,直接到下一个then的onRejected
reject(this.#PromiseResult)
}
}
// onFulfilled, onRejected什么时候执行
// resolve, reject什么时候执行
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.#handlers.push({
onFulfilled,
onRejected,
resolve,
reject,
})
this.#execCallback()
})
}
}