共计 6536 个字符,预计需要花费 17 分钟才能阅读完成。
Promise
一、promise 的简略应用
new Promise((resolve, reject) => {resolve("ok")
}).then(data => {console.log(data) //OK
}, error => {console.log(error)
})
// 简化下
let promise = new Promise(executor)
promise.then(onFulfilled, onRejected)
须要留神的是
executor
是一个会被立刻执行的回调函数, 该函数带有两个参数,resolve
和reject
- 如果
executor
中调用了resolve(value)
, 那么这个value
则会被传给onFulfilled
, 如第一个例子中console.log(data)
输入为ok
- 如果
executor
中调用了reject(value)
, 那么这个value
则会被传给onRejected
,作为onRejected
的实参 - 还有一点须要留神的是,promise 是带有状态的,开始默认为 pending, 当调用
resolve
后,状态变更为fulFilled
, 当调用reject
后,状态变更为rejected
。当状态从pending
变更为fulFilled / reject
后,状态不可再扭转
二、Promise 的高级实现
让咱们持续带着第一个用例 来做个 promise 的高级实现
new Promise((resolve, reject) => {resolve("ok")
}).then(data => {console.log(data) //OK
}, error => {console.log(error)
})
// 咱们带着例子逐行实现
// let executor = (resolve, reject) => {resolve("ok") }
// new Promise(executor)
class Promise {constructor(executor){
this.status = "pending" // 状态默认为期待态
//executor = (resolve, reject) => {resolve("ok") }
// 传入的 executor 是一个带有两个参数的函数,
// 并且参数 resolve 和 reject 都是可调用的函数
// 所以咱们应该先申明这两个函数 而后当成实参传入 executor
const resolve = (value) => { }
const reject = (error) => { }
executor(resolve,reject)
}
}
// let executor = (resolve, reject) => {resolve("ok") }
// new Promise(executor)
class Promise {constructor(executor){
this.status = "penging"
this.resValue = null
this.rejValue = null
// executor = (resolve, reject) => {resolve("ok") }
const resolve = (value) => {// 如 resolve("ok") 中传入的 "ok"
// 须要在前面代码的 then 的 onFulilled 中拿, 故须要存储这个 value
this.resValue = value
// 并且调用 resolve 后,状态更改为 fulfilled
if(this.status === "pending"){this.status = "fulfilled"}
}
const reject = (error) => {
this.rejValue = error
if(this.status === "pending"){this.status = "rejected"}
}
executor(resolve,reject)
}
}
// let promise = new Promise(executor)
// promise.then(onFulfilled, onRejected)
// 能够得出 promise 须要一个 then 办法
class Promise {constructor(executor){// 如上...}
then(onFulfilled, onRejected){
// 调用 then 办法的时候, 要判断是以后状态是胜利还是失败
if(this.status === "fulfilled"){
// 如果以后是胜利态
onFulfilled(this.value)
}
if(this.status === "rejected"){
// 如果以后是失败态
onRejected(this.error)
}
}
}
这样算是根本实现了 promise 的高级性能, 然而当
new promise(executor)
传入的executor
为异步函数的时候,就会呈现问题。如下:
new Promise((resolve,reject)=>{setTimeout(()=>{resolve("ok")
},0)
}).then(data => {console.log(data) // 不会输入 ok
})
// 其起因是: 当 executor 为异步函数传入 new Promise` 时
// 尽管立刻调用了 executor, 然而其为异步函数, 会被推入微工作, 不会马上执行
// 所以上面这个 resolve 不会马上执行,会先执行宏工作的 then 办法
// 所以在执行 then 办法的时候,promise 的状态依然为 pending
class Promise {constructor(executor){// executor = setTimeout(()=>{resolve("ok")},0)
const resolve = (value) => {
// ** 2. 后执行
this.value = value
if(status === "pending"){this.status = "fulfilled"}
}
// ...
executor(resolve,reject)
}
then(onFulfilled, onRejected){
// ** 1. 先执行
if(this.status === "fulfilled"){onFulfilled(this.value)
}
// ...
}
}
Promise 的高级实现之异步改良
当初的问题是, 在传入异步函数的时候,咱们执行到
then
办法的时候, 状态还是为pending
, 所以无奈执行到onFulfilled
。咱们又须要在executor
中调用了resolve
后执行onFulfilled
。所以很天然的想到了应用公布订阅模式来解决。即在then
中判断到以后为期待态时 (那executor
肯定是异步函数), 将onFulfilled
和onRejected
存起来, 在executor
中执行到 resolve 后 执行onFulfilled
。上面是代码实现:
class Promise {constructor(executor){
this.status = "pending"
//onFulfilled 汇合
this.onFulfilledCallbacks = [ ]
//onRejected 汇合
this.onRejectedCallbacks = [ ]
const resolve = (value) => {
this.resValue = value
if(status === "pending"){
this.status = "fulfilled"
// 公布
this.onFulfilledCallbacks.forEach(callback => {callback(this.value)
})
}
}
const reject = (error) => {
this.rejValue = error
if(status === "pending"){
this.status = "rejected"
this.onRejectedCallbacks.forEach(callback => {callback(this.error)
})
}
}
executor(resolve,reject)
}
then(onFulfilled, onRejected){
// 同步代码不变, 减少异步状况代码
if(this.status === "fulfilled"){onFulfilled(this.value)
}
if(this.status === "rejected"){onRejected(this.error)
}
// 新增代码
if(this.status === "pending"){
// 曾经到 then 了,status 的状态还没有扭转。// 阐明 executor 中为异步函数
// 订阅
this.onFulfilledCallbacks.push((data)=>{
// 切片
onFulfilled(data)
})
this.onRejectedCallbacks.push((error)=>{onRejected(error)
})
}
}
}
以上就是 promise 的高级实现,promise 的外围在于他们链式调用。咱们在下一章具体介绍
三、理解 promise 的链式调用
new Promise((resolve,reject) => {resolve("hello")
}).then(data => {console.log(data) //hello
return "world"
}).then(data => {console.log(data) //world
})
如果在 then 中
return
一个简略值 (非promise
), 那么将在下一个 then 中的onFulfilled
取到这个值。
new Promise((resolve,reject) => {resolve("hello")
}).then(data => {throw new Error()
}).then(data => {console.log(data)
},error => {console.log(error) // Error
})
如果在 then 中抛出异样, 那么将会在下一个 then 的
onRejected
拿到这个异样。
let promise1 = new Promise((resolve,reject) => {resolve("hello")
}).then(data => {return data})
console.log(promise1) // Promise{<fulfilled>: "hello"}
// 能够看得出来: 在 then 办法中, 会返回一个 promise 对象
// 因为 promise 的状态不可二次扭转, 所以返回的应该是一个新的 promise 对象
四、测试案例剖析
在实现 promise 的链式调用前, 首先要有个测试案例:
let promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve("the message is")
}, 0);
})
let promise2 = promise1.then(data => {let interPromise = new Promise((resolve,reject) => {setTimeout(() => {resolve(data + "that today is a happy day")
}, 0);
})
return interPromise
}, null)
我感觉有必要先剖析下这个 promise2
- 1. 首先咱们晓得这个
promise1.then()
肯定是返回一个新的promise
, 而且是一个带着实现或完结态的promise
- 2. 所以在
then
的外部生成一个promise
, 并且在外部实现了这个promise
的resolve(data)
, 而且这个data
来之外部的interPromise
的resolve()
- 3. 再看下这个
interPromise
, 他要想把外部的resolve(data + "that today is a happy day")
里的数据传给下层then
的promise
, 那么只能是隐性的调用interPromise
的then
, 并且在这个then
中, 调用下层promise
的resolve
- 这是
promise
中的最难点, 如果没看懂, 能够多看几遍, 糊涂的话能够先看上面的代码实现,再回过头来看这段剖析
let promise3 = promise2.then(data => {console.log(data) // expect: the message is that today is a happy day
})
六、promise 的链式调用
该案例为了不便浏览和了解,就实现了最难的性能, 并且省略了异样捕捉等内容。
// constructor 不变,只对 then 办法进行了批改
class Promise {constructor(executor) {
this.status = "pending"
this.resValue = null
this.rejValue = null
this.onfulfilledCallbacks = []
this.onrejectedCallbacks = []
const resolve = (value) => {
this.resValue = value
if (this.status === "pending") {
this.status = "fulfilled"
this.onfulfilledCallbacks.forEach(callback => {callback(this.resValue)
})
}
}
const reject = (error) => {
this.rejValue = value
if (this.status === "pending") {
this.status = "rejected"
this.onrejectedCallbacks.forEach(callback => {callback(this.rejValue)
})
}
}
executor(resolve, reject)
}
then(onFulfilled, onRejected) {// onFulfilled = data => new Promise(...)
//then 办法返回 promise2
const promise2 = new Promise((resolve2,reject2) => {if (this.status === "pending") {
//async
// 这里须要一个实现一个异步
// 因为在 resolvePromise 中须要 实现初始化的 promise2
setTimeout(()=>{
this.onfulfilledCallbacks.push(data => {
// 代入案例来看
// 这个 x = interPromise
let x = onFulfilled(data)
// 而后判断这个 x 是否是一个 promise
resolvePromise(x, resolve2, reject2)
})
this.onrejectedCallbacks.push(error => {
// 类比下面进行批改,这里不做批改
onRejected(error)
})
},0)
}
// 上面状况和下面同理,我不做批改
if (this.status === "fulfilled") {onFulfilled(this.resValue)
}
if (this.status === "rejected") {onRejected(this.rejValue)
}
})
return promise2
}
}
function resolvePromise(x, resolve2, reject2){
// 源码中有许多判断的异样捕捉,这里就实现最外围的代码
if((typeof x === "object" && typeof x !== "null")|| typeof x === "function"){
// x is a object or function
let then = x.then
if(typeof then === "function"){
// 在这里调用 interPromise 的 then
// 并且调用下层 promise 的 resolve
then.call(x,data => resolve2(data),null)
// x is a promise
// for example: x = new promise((resolve,reject) => {resolve("ok")})
}
}
}
正文完
发表至: javascript
2020-12-30