深刻理解Promise系列(二):手把手教你实现Promise(

2017-06-27  本文已影响0人  任无名F

:经过作者的进一步学习,觉得有更好的串行Promise的实现,有兴趣的读者可以移步这里


串行的Promise,质的飞跃

接下来要介绍的,是Promise最为有趣与神秘的功能——串行Promise。
它的效果是当前promise达到fulfilled状态之后,会开始下一个promise。例如ajax获取用户id后,再根据用户id获取用户的其他信息,比如:

function p1() {
  return new Promise(function(resolve, reject) {
    $.get("/userId", function(id) {
      resolve(id);
    });
  });
}
function p2(id) {
  return new Promise(function(resolve, reject) {
    $.get("/userInfo?id=" + id, function(info) {
      resolve(info);
    });
  });
}
p1().then(p2).then(function(info) {
  console.log(info); // 此处输出用户信息
});

这个方法的难点在于,如何衔接当前promise与后邻promise,这需要对then方法进行彻底的改造:

  this.then = function(onFulfilled) {
    return new Promise(function(resolve) {
      handle({
        onFulfilled: onFulfilled || null,
        resolve: resolve
      });
    });
  }
  function handle(deferred) {
    if(state === "pending") {
      deferreds.push(deferred);
      return;
    }
    let ret = deferred.onFulfilled(value); // 【核心3】,resolve作为onFulfilled传入的情况
    if(ret) {
      deferred.resolve(ret); // 【核心1】,onFulfilled有返回值的情况,且ret有可能为promise
    } else {
      deferred.resolve(value); // 【核心4】,onFulfilled无返回值的情况
    }
  }

为了衔接前后两个promise,让then返回了一个桥接的promise,并添加handle方法来处理onFulfilled。因为此时的onFulfilled很可能会返回一个Promise实例,所以我们需要继续改造resolve方法,用于处理参数为promise的情况。这也是最后的冲刺!

  function resolve(newValue) {
    if(newValue && (typeof newValue === "object" || typeof newValue === "function") {
      let then = newValue.then;
      then.call(newValue, resolve); // 【核心2】
      return;
    } else {
      state = "fulfilled";
      value = newValue;
      setTimeout(() => {
        deferreds.forEach((deferred) => {
          handle(deferred);
        });
      }, 0);
    }
  }

现在,我们的resolve支持传入一个Promise实例了,而且针对promise与普通值的不同,它会执行两条互不干扰的支线方法。
此时我们回到开头的例子:

function p1() {
  return new Promise(function(resolve, reject) {
    $.get("/userId", function(id) {
      resolve(id);
    });
  });
}
function p2(id) {
  return new Promise(function(resolve, reject) {
    $.get("/userInfo?id=" + id, function(info) {
      resolve(info);
    });
  });
}
p1().then(p2).then(function(info) {
  console.log(info); // 此处输出用户信息
});

参考资料剖析 Promise 之基础篇

上一篇 下一篇

猜你喜欢

热点阅读