恋の歌的logo
Auto
归档 标签

手写Promise笔记

发表于2020-06-12 10:34
更新于2023-02-13 18:28
分类于编程
总字数622
阅读时长 ≈2 分钟

手写Promise笔记

掘金上看见一个20行的Promise实现,主要是链式调用,感觉很不错,学习学习。

原文出处:最简实现Promise,支持异步链式调用(20行)

Promise 🔗

直接上代码吧。

javascript
// Promise构造函数
function Promise(excutor) {
  var self = this;
  self.onResolvedCallback = [];
  function resolve(value) {
    setTimeout(() => {
      self.data = value;
      self.onResolvedCallback.forEach(callback => callback(value));
    },0);
  }
  excutor(resolve.bind(self));
}
// Promise的then调用函数
Promise.prototype.then = function(onResolved) {
  var self = this;
  return new Promise(resolve => {
    self.onResolvedCallback.push(function() {
      var result = onResolved(self.data);
      if (result instanceof Promise) {
        result.then(resolve);
      } else {
        resolve(result);
      }
    });
  })
}

参数excutor为一个函数,这个函数有两个参数。

一个是resolve,一个是reject,这个实现为简单实现,所以没有第二个参数,主要为实现链式调用。

Promise构造函数中的onResolvedCallback为一个待调用的函数数组。

当通过then函数注册回调的时候,会把回调函数存在onResolvedCallback数组中。

then函数规范中有提到,必须返回一个新的Promise对象,基于这个可以实现链式调用。

then如何返回也在规范中有提及,如果回调函数返回了一个Promise,那么then返回的Promise就要使用函数返回的Promise的值(value)。

如果不是函数返回的不是Promise,那么then返回的Promise就直接以这个值来解决。

resolve函数是一个完成函数,会把Promise的状态从pending转为resolved,并且调用全部注册的回调。

resolve为啥要通过setTimeout调用呢?可以看下面的代码。

javascript
var promise = new Promise(function(resolve,reject) {
    resolve('success');
});
// 上面的操作就已经调用了数组中的回调
// 下面的注册的回调就会无效了
promise.then(res=>{
    console.log(res);
});

我们构建了一个promise,直接的将这个promise解决掉(调用resolve)。

resolve会把onResolvedCallback的函数逐一地执行。

注意,这时候的操作都是同步的,也就是这时的then注册回调还没有执行,导致了then方法没有被执行。

使用了setTimeout,使得更改状态以一个新的任务执行,也就是在当前代码执行完之后再执行,使得回调函数可以注册到onResolvedCallback里面。使得then的表现正常。

需要注意,Promise应该是以微任务的形式来进行resolve的,而不是以任务,这个在之前的关于taskmicrotask的文章中有说到。

#JavaScript
#Promise
哦呐该,如果没有评论的话,瓦达西...