最简实现Promise

avatar

最简实现 Promise

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function Promise(fn) {
this.cbs = []

const resolve = (value) => {
setTimeOut(()=>{
this.data = value
this.cbs.forEach((cb) => cb(value))
})
}

fn(resolve)
}

Promise.prototype.then = function(onResolved) {
return new Promise((resolve) => {
this.cbs.push(()=>{
const res = onResolved(this.data)
if(res instanceof Promise){
res.then(resolve)
}else{
resolve(resolve)
}
})
})
}

分析

先上使用例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
new Promise((resolve,reject) => {
setTime(() => {
resolve(1)
},1000)
})
// then1
.then(res => {
return new Promise((resolve,reject) => {
setTimeOut(() => {
resolve(2)
}, 2000)
})
// then2
.then(res => {
console.log(res)
})
})

首先分析Promise构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 此处fn为new Promise传入的函数
function Promise(fn) {
// 在实例上挂载Promise resolve时的回调函数集
this.cbs = []

// 传递给Promise处理函数的resolve,相当于是原生Promise中入参处理函数中,取到的第一个参数resolve
// 在实例上挂载处理函数的结果,并执行一遍回调函数集
const resolve = (value) => {
setTimeOut(() => {
this.data = value
this.cbs.forEach((cb) => cb(value))
})
}

// 执行用户传入的函数
// 并且把resolve方法交给用户执行
fn(resolve)
}

Promise最重要的是链式调用,重点在then的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Promise.prototype.then = function(onResolved) {
// 此处this指向上面的构造函数作用域
return new Promise((resolve) => {
// 每一个then,都会往this.cbs推入一个执行栈,等待后续执行
this.cbs.push(() => {
// 此处的onResolved为then内部的入参,res为执行结果
const res = onResolved(this.data)
// 如果res执行结果依旧为Promise的原型链上,即内部return new Promise,则继续将resolve传递入下一个then
if(res instanceof Promise) {
res.then(resolve)
}else {
resolve(res)
}
})
})
}
结合例子
  1. 第一次 new Promise() 执行时,返回的实例称为 promise1
  2. then 的实现中,返回的实例称为 promise2
  3. 第一次 new Promise().then 中,用户手动 return new Promise() 这里称为 user promise
  4. promise2 中的this,其实指向 promise1。在 promise2 中的函数会往this.cbs推入,等待执行
  5. this.cbs.push() 中的函数,只有在 promise1 resolve后才会执行。如果用户传入给 then 的执行函数中 (onResolved ) 返回了 user promise ,用户会在合适的时机执行 resolve promise2 ,这时内部的 if (res instanceof Promise) { res.then(resolve) } 就会执行
  6. then2 中的函数只有在 promise2 resolve 后才会执行,此时 then2 是挂载到 promise2 的cbs中的,最终实现异步链式调用