承诺不叫“然后”回调

时间:2016-06-10 18:13:54

标签: javascript node.js asynchronous promise async-await

C#/ Dart的async / await功能让我有点失望。我注意到ES7有类似语法的提议,there is a library将该功能添加到Node.JS应用程序。

此库在浏览器中不起作用。我想通过尝试编写我自己的迷你解决方案可能会帮助我了解原因,所以我决定尝试一下,只是为了教育自己。 This is my attempt so far,关于Github Gist。我在下面写了一些片段。

await函数中:

function await (promise) {

  /* PromiseState declared here */

  var self = {
    result: null,
    state: PromiseState.pending
  };

  function onPromiseUpdate(context, newState) {
    return function (value) {
      console.log("Promise Updated!");
      context.result = value;
      context.state = newState;
    }
  }

  console.log("awaiting");
  // this never shows the Promise to be pending (using example below)
  console.log(promise);
  promise
    .then(onPromiseUpdate(self, PromiseState.resolved)) // this is never called
    .catch(onPromiseUpdate(self, PromiseState.rejected));

  // Shouldn't this not block the app if it's inside a Promise?
  while (self.state == PromiseState.pending) ;
  console.log("delegating");

  /* just returning the value here */
}

示例:

// is there another way to pass 'await' without a parameter?
unstableFunc = async(function (await) { 
  console.log("running unstable");
  if(Math.random() > 0.5) return Math.random() * 15 + 5;
  else throw "fail";
});

expensiveFunc = async(function (await, x, y) {
  result = await(unstableFunc())
  for (var i = y * 8; i >= 0; i--) {
    result *= i ** y / x;
    console.log(result);
  }
  return result;
});


window.addEventListener('load', function () {
  console.log("about to do something expensive");
  // 'expensiveFunc' returns a Promise. Why does this block the webpage?
  expensiveFunc(10, 2).then(function (val) {
    console.log("Result: " + val.toString());
  });
  console.log("called expensive function");
});

运行此操作时,浏览器无法完成加载。这与我设置的循环有关,以检查正在解决的Promise的状态,但这不是我的问题的焦点。我想知道的是为什么thencatch回调都没有被调用。记录时,控制台永远不会记录待处理的Promise,而且我一直认为thencatch如果未来未处于待处理状态,会立即执行回调。在这种情况下,为什么不是这样呢?

1 个答案:

答案 0 :(得分:1)

到达/执行此代码行的那一刻:

while (self.state == PromiseState.pending) ;

您的脚本将永久被阻止(或者直到选项卡崩溃或浏览器将其终止)。当该循环正在运行时,回调不能运行(也不能运行任何其他),因此您的promise状态永远不会更改为pending,从而导致无限循环。承诺涉及不会改变上述任何一项。