最简实现Promise支持异步链式调用解读大佬的文章

38次阅读

共计 3245 个字符,预计需要花费 9 分钟才能阅读完成。

今天瞅了下 ssh 大神的《最简实现 Promise,支持异步链式调用(20 行)》这篇文章 还真的是从进阶到入院(人已疯!!!)
我尝试直接去阅读这 20 代码 表示根本看不懂

function Promise(fn) {this.cbs = [];

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

  fn(resolve.bind(this));
}

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(res);
      }
    });
  });
};

这就是那 20 行代码
我承认我是个笨鸟 没那个大局观 所以只能用自己的办法去理解 就是逐行的分析 拿原生 js 对比对(感觉在作弊)
先上原生 js

new Promise((resolve) => {setTimeout(() => {resolve(1)
    })
  })
  .then((res) => {console.log("res", res)
    return 2
    // return new Promise((resolve) => {//   setTimeout(() => {//     resolve(2)
    //   })
    // })
  })
  .then((res) => {console.log("res", res)
  })

分析:
1、Promise 是个构造函数 传递函数 fn 函数 fn 接收函数 resolve
2、函数 resolve 传递 res
3、构造函数 Promise 的原型上有个函数 then 函数 then 传递函数 onResolved
4、函数 onResolved 接收 res
分析后去代码实现

function Promise(fn) {function resolve(value) { }
  fn(resolve.bind(this))
}
Promise.prototype.then = function (onResolved) {}

这里有个重点 因为 new Promise(() => {})传递的函数 fn 是直接执行的 所以构造函数 Promise 的内部直接调用了函数 fn

然后考虑如何把 resolve(1)和 then((res) => {res // 1})串联上

function Promise(fn) {this.cbs = []

  function resolve(value) {this.cbs.forEach((cb) => {cb(value)
    });
  }
  fn(resolve.bind(this))
}
Promise.prototype.then = function (onResolved) {this.cbs.push(onResolved)
}

这里通过定义了一个 cbs 函数集 通过函数 then 去收集函数 onResolved 然后函数 resolve 去触发 看似没问题 其实是没效果的 因为还没有来得及收集 就触发了
真正的代码应该这样

function Promise(fn) {this.cbs = []

  function resolve(value) {setTimeout(() => {this.cbs.forEach((cb) => {cb(value)
      });
    })
  }
  fn(resolve.bind(this))
}
Promise.prototype.then = function (onResolved) {this.cbs.push(onResolved)
}

函数 resolve 的方法体内加了个 setTimeout 这个 setTimeout 的作用有俩 一是确实触发函数 resolve 是个异步操作 二是保证先收集完再触发 现在就基本成型了

最后就是考虑如果链式调用 .then(() => {}).then(() => {}) 这块属实烧到我了 基本就是靠着比对去理解
首先如果想链式.then(() => {}).then(() => {}) 那么第一个.then(() => {})完后 返回的也应该是一个 Promise 实例 所以代码应该长成这样

function Promise(fn) {this.cbs = []

  function resolve(value) {setTimeout(() => {this.cbs.forEach((cb) => {cb(value)
      });
    })
  }
  fn(resolve.bind(this))
}
Promise.prototype.then = function (onResolved) {return new Promise((resolve) => {this.cbs.push(onResolved)
  })
}

但是这样.then(() => {}).then(() => {})第二个.then(() = >{})并不会被触发 所以需要手动触发 对了 第二个.then(() => {})是属于 return new Promise 的 这个很重要

function Promise(fn) {this.cbs = []

  function resolve(value) {setTimeout(() => {
      this.data = value
      this.cbs.forEach((cb) => {cb(value)
      });
    })
  }
  fn(resolve.bind(this))
}
Promise.prototype.then = function (onResolved) {return new Promise((resolve) => {this.cbs.push(() => {const res = onResolved(this.data)
      resolve(res)
    })
  })
}

考虑到.then(() => {return 2}).then((res) => {res // 2})会有这样一个效果 所以 push 函数 onResolved 就需要包裹一层函数 这样就能够处理函数 onResolved 的返回值 res 然后再触发 return new Promise 的
resolve(res) 就可以触发第二个.then((res) => {res // 2}) 就可以接受到 2 了

真真最后还需要考虑到.then(() => {return new Promise((resolve) => {setTimeout(() => {resolve(2)}, 500)})}).then((res) => {res // 2})这种效果 所以继续改造

function Promise(fn) {this.cbs = []

  function resolve(value) {setTimeout(() => {
      this.data = value
      this.cbs.forEach((cb) => {cb(value)
      });
    })
  }
  fn(resolve.bind(this))
}
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(res)
      }
    })
  })
}

解释一下 如果函数 onResolved 的返回值 res 是构造函数 Promise 的实例 那么调用流程是这样的 首先 res.then 方法会收集 return new Promise 的 resolve 然后.then(() => {return new Promise((resolve) => {setTimeout(() => {resolve(2)}, 500)})})这个 resolve(2)就会触发 return new Promise 的 resolve 最后执行 return new Promise 的.then 也就是第二个.then

写的有点乱
客观对付看
skr…

正文完
 0