实现简单承诺的finally方法

时间:2019-08-18 22:17:23

标签: javascript es6-promise

我试图从头开始实现承诺。

问题:

  

我不确定如何实现“最终”? (我猜想最终会   然后在执行并捕获。 (仅一次))

如果您认为可以对我的代码进行任何重构,请随时提出建议。这是我天真地兑现承诺的尝试。

这是我的实现方式

function Promisify(fn) {
  let status = 0; // 0 = unfulfilled, 1 = resolved, 2 = rejected
  let result;
  let error;
  let thenFns = [];
  let catchFns = [];
  let finallyFn = undefined;

  // Public Methods.
  this.then = function(fn) {
    thenFns.push(fn);
    doThen();
    return this; // for chaining
  };
  this.catch = function(fn) {
    catchFns.push(fn);
    doCatch();
    return this; // for chaining
  };

  // TODO: Implement finally
  this.finally = function(fn) {
      finallyFn = fn;
    //   dofinally(fn);
      return this;
  }
  
  // Private Methods
  function resolve(r) {
    if (status) throw Error('can not resolve, already handled');
    status = 1;
    result = r;
    doThen();
  }

  function reject(e) {
    if (status) throw Error('can not reject, already handled');
    status = 2;
    error = e;
    doCatch();
  }

  function doThen() {
    if (status === 1) {
      while(thenFns.length) {
        thenFns.shift()(result);
      }
    }
  }

  function doCatch() {
    if (status === 2) {
      if (catchFns.length === 0) {
        console.error('uncaught error')
      }
      while(catchFns.length) {
        catchFns.shift()(error);
      }
    }
  }
  
  try {
    fn(resolve, reject);
  } catch (e) {
    reject(e);
  }
}

// ========  QUESTION: Caller ================
const demoFail = new Promisify((resolve, reject) => {
    setTimeout(function() {
        reject('Howdy! from DemoFail')
    }, 1000);
});

demoFail
    .then(val => console.log("DemoFail Then!!"))
    .catch(console.error) //Should throw an error.
    .then(val => console.log("Second then!"))
    .catch(
    (err) => {
        throw new Error('error', err);
    })
    .finally(val => console.log("Executed Finally"))

1 个答案:

答案 0 :(得分:1)

实现中缺少一些内容:

  1. .then()需要返回一个新的承诺,而不是相同的承诺。
  2. .then()处理程序的返回值(如果不是承诺)将成为在步骤#1中返回的新返回的承诺的解析值。
  3. 如果.then()处理程序的返回值是一个Promise,则直到从.then()处理程序返回的Promise解析或拒绝该值之前,步骤1中新返回的Promise才会解析。
  4. 在调用.then()处理程序时,您需要在对处理程序的调用周围进行try / catch,因为如果处理程序抛出,则将返回到步骤1的承诺变成拒绝的承诺,抛出错误为拒绝原因。
  5. 所有.catch()处理程序都有类似的逻辑(它还会返回一个新的Promise,并且该处理程序的返回值会影响从步骤#1新返回的Promise)。
  6. 存储.then().catch()回调fns时,还需要存储为每个回调单独返回的新创建的Promise,因为该Promise将受到返回值或抛出的异常的影响回调。

涵盖此方面的规范本身非常简单。您可以阅读here。而且,这是该规范的an implementation

您的简单版本看起来可能像fn().then()这样的一个承诺级别,但是它没有进行正确的链接并且没有在处理程序中捕获异常,也没有注意处理程序中的返回值这些都是承诺的相当基本的行为。不幸的是,没有超级简单的方式来写包括基本行为在内的承诺。只需更多代码即可支持它们。