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

今天瞅了下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...

你可能感兴趣的:(前端,javascript)