扔进一个承诺里面的回调

时间:2016-08-31 09:15:36

标签: javascript node.js promise throw

我知道stackoverflow充满了类似的问题,我已经阅读了很多。

从我得到的内容中throw承诺应拒绝它,正如我在documentation中所读到的那样:

  

如果执行程序抛出异常,则其值将传递给拒绝解析函数。

但即使在阅读了很多关于承诺和投掷的帖子后,我仍然不理解我正在粘贴的代码片段及其发生的原因。

function foo(a, b, cb) {
  setTimeout(() => {
    cb('Inner error *!?"$%&#@"');
  }, 0);
}

const getThePromise = () => {
  return new Promise((resolve, reject) => {
    const cb = (err) => {

      /* >>> ************ */

      throw err;       // catch not called
      // reject(err);  // catch called

      /* ************ <<< */

    }
    foo('foo', 'dudee', cb);
  });
}

getThePromise()
.catch((err) => {
  console.log('CATCH:', err);
})
.then((res) => {
  console.log('then...');
})

我不明白为什么如果我使用throw没有调用承诺的.catch但是如果我使用reject则调用它。

为了澄清我在Mac OS / X 10.11中使用Node.js v6.2.2,但我认为它也不是浏览器问题。

1 个答案:

答案 0 :(得分:3)

您在异步setTimeout调用中抛出错误,这将导致未被捕获的错误。异步代码不会在try-catch块的相同上下文中执行。这与promise API无关。这只是JavaScript中异步代码执行行为的一部分。

看一下下面的例子。

&#13;
&#13;
const asyncOperation = err => {
  try {
    setTimeout(function() {
      throw err; // will be dropped onto the event queue
      // until the call stack is empty
      // even if this takes longer than
      // a second.
    }, 1000);
  } catch (e) {
    console.log(e) // will not be called
  }
}

asyncOperation('Inner error *!?"$%&#@"')
&#13;
&#13;
&#13;

现在是setTimeout调用中的try-catch块的相同示例,并且在try块中抛出了错误。

&#13;
&#13;
const asyncOperation = err => {
  setTimeout(function() {
    try {
      throw err // here the error will be throw inside
    } catch (e) { // the try block and has the same execution 
      console.log(e) // context.
    }
  }, 1000);
}

asyncOperation('Inner error *!?"$%&#@"')
&#13;
&#13;
&#13;

您可以在此处找到有关Promise.catch的更多信息。

  

Promise.prototype.catch()

     

catch()方法返回一个Promise并仅处理被拒绝的案例。

实际上有一个示例与您在示例中描述的情况相同。看看

Gotchas when throwing errors

// Errors thrown inside asynchronous functions will act like uncaught errors
var p2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    throw 'Uncaught Exception!';
  }, 1000);
});

p2.catch(function(e) {
  console.log(e); // This is never called
});