最简实现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中的,最终实现异步链式调用