美文网首页
Promise的简易实现(2)

Promise的简易实现(2)

作者: SunnyEver0 | 来源:发表于2018-07-14 14:32 被阅读9次

    在上一篇文章里面,我们实现了一个简单的Promise,已可以满足一些较简单的场景。但却无法进行then的Promise链式衔接,比如这样:

    getUserId()
        .then(getUserInfoById)
        .then(function (info) {
            
        });
    
    function getUserJobById(id) {
        return new Promise(function (resolve) {
            fetch(baseUrl + id, function(res) {
                resolve(res);
            });
        });
    }
    

    这种场景相信用过promise的人都知道会有很多,那么类似这种就是所谓的链式Promise

    链式Promise是指在当前promise达到fulfilled状态后,即开始进行下一个promise(后邻promise)。那么我们如何衔接当前promise和后邻promise呢?(这是这里的难点)。

    只需在then方法里面return一个promise就好啦。可见Promises/A+规范中的2.2.7
    Promise/A+规范

    then must return a promise [3.3].

    function RPromise(fn) {
      var state = 'pending',
        value = null,
        callbacks = []; //callbacks为数组,因为可能同时有很多个回调
    
    
      this.then = function (onFulfilled) {
        return new RPromise(function (resolve) {
          handle({
            onFulfilled: onFulfilled || null,
            resolve: resolve
          });
        });
      };
      // this.then = function (onFulfilled) {
      //   if (state === 'pending') {
      //     callbacks.push(onFulfilled);
      //     //ask 为什么要return this?
      //     return this;
      //   }
      //   //假如state已经切换至其他状态,直接执行回调
      //     setTimeout(function () {
      //         onFulfilled(value);
      //     }, 0);
      //
      //   return this;
      // };
    // 关键tip-2
    // 1: 链式promise之间有一个桥梁promise,可称之为bridge promise,用于衔接两个promise,包装在then函数中
    // 2: 当前一个promise resolve之后,bridge promise负责传递之前promise的值
    // 3: 将当前promise的值和bridge promise的resolve方法传给下一个promise之后,在下一个promise resolve的时候,执行bridge promise的resolve方法,再执行本身后注册的then函数中的promise resolve
    // 4: 执行完四个promise(promise 1 - getUserId, promise 2 - getUserId bridge, promise 3 - getUserInfoById, promise 4 - getUserInfoById bridge)之后,继续执行后面的then函数
      function handle(callback) {
        if (state === 'pending') {
          callbacks.push(callback);
          return;
        }
        //如果then中没有传递任何东西
        if (!callback.onFulfilled) {
          callback.resolve(value);
          return;
        }
    
        var ret = callback.onFulfilled(value);
        callback.resolve(ret);
      }
    
      function resolve(newValue) {
    
        state = 'fulfilled';
        value = newValue;
    
        // Promises/A+规范明确要求回调需要通过异步方式执行,用以保证一致可靠的执行顺序
        // 保证then函数的回调都已注册完毕
        // 比如promise内部的函数是同步函数
        // function getUserId() {
        //     return new Promise(function (resolve) {
        //         resolve(9876);
        //     });
        // }
        // getUserId().then(function (id) {
        //     // 一些处理
        // });
    
        if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
          var then = newValue.then;
          if (typeof then === 'function') {
            then.call(newValue, resolve);
            return;
          }
        }
        state = 'fulfilled';
        value = newValue;
        // console.log('value' + value);
        setTimeout(function () {
          callbacks.forEach(function (callback) {
            handle(callback);
          });
        }, 0);
      }
    
      fn(resolve);
    }
    
    //eg:
    var testAsyncFunc1 = function () {
      return new RPromise(function (resolve) {
        // resolve(123);
        setTimeout(function () {
          resolve(123)
        }, 100)
      })
    };
    
    var testAsyncFunc2 = function (res) {
      return new RPromise(function (resolve) {
        setTimeout(function () {
          resolve(res + 456)
        }, 100);
      })
    };
    
    testAsyncFunc1()
      .then(testAsyncFunc2)
      .then(function (res) {
        console.log(res);
      });
    
    console.log(456);
    

    1.then方法中,创建并返回了新的Promise实例,这是串行Promise的基础,并且支持链式调用。
    2.handle方法是promise内部的方法。then方法传入的形参onFulfilled以及创建新Promise实例时传入的resolve均被push到当前promise的callbacks队列中,这是衔接当前promise和后邻promise的关键所在(这里一定要好好的分析下handle的作用)。
    3.testAsyncFunc1生成的promise(简称testPromise1)异步操作成功,执行其内部方法resolve,传入的参数正是异步操作的结果123
    4.调用handle方法处理callbacks队列中的回调:testAsyncFunc2 方法,生成新的promise(testAsyncFunc2 promise)
    5.执行之前由testAsyncFunc1 promise的then方法生成的新promise(称为bridge promise)的resolve方法,传入参数为testAsyncFunc1 promise。这种情况下,会将该resolve方法传入testAsyncFunc2 promise的then方法中,并直接返回。
    6/在testAsyncFunc2 promise异步操作成功时,执行其callbacks中的回调:testAsyncFunc1 bridge promise中的resolve方法
    7.最后执行testAsyncFunc1 bridge promise的后邻promise的callbacks中的回调。

    // 关键tip-2
    1: 链式promise之间有一个桥梁promise,可称之为bridge promise,用于衔接两个promise,包装在then函数中 2: 当前一个promise resolve之后,bridge promise负责传递之前promise的值
    3: 将当前promise的值和bridge promiseresolve方法传给下一个promise之后,在下一个promise resolve的时候,执行bridge promiseresolve方法,再执行本身后注册的then函数中的promise resolve
    4: 执行完四个promise(promise 1 - getUserId, promise 2 - getUserId bridge, promise 3 - getUserInfoById, promise 4 - getUserInfoById bridge)之后,继续执行后面的then函数

    相关文章

      网友评论

          本文标题:Promise的简易实现(2)

          本文链接:https://www.haomeiwen.com/subject/yvnepftx.html