在Q中学习承诺和例外与拒绝

时间:2013-11-18 06:46:40

标签: javascript node.js promise q

我的印象是,promise中的异常会触发后续的失败处理程序,但我在这段代码中没有看到它:

var Q = require('q');

function x() {
  console.log('x');
  var deferred = Q.defer();

  setTimeout(
      function() {
        console.log('resolving x');
        deferred.resolve('hi');
      },
      1000
  );

  return deferred.promise;
}

function y() {
  console.log('y');
  var deferred = Q.defer();

  setTimeout(
      function() {
        console.log('throwing in y');
        throw new Error('Oih!');
      },
      1000
  );

  return deferred.promise;
}

x().then(y).then(
    function () {
      console.log('yes');
    },
    function () {
      console.log('no');
    }
);

我做错了什么,或者我误解了?

2 个答案:

答案 0 :(得分:3)

你正在混合回调和承诺+你有一个延迟反模式的情况。使用Q.delay或包装如:

function delay(ms) {
    var d = Q.defer();
    setTimeout(d.resolve, ms);
    return d.promise;
}

现在有超时的promise API,没有理由使用setTimeout:

function x() {
    return delay(1000).then(function () {
        console.log("hi");
    });
}

function y() {
    return delay(1000).then(function () {
        console.log('throwing in y');
        throw new Error('Oih!');
    });
}

使用:

x()
.then(y)
.then(function() {
    console.log('yes');
})
.catch(function(e) {
     console.log('no');
});

答案 1 :(得分:0)

承诺链中的所有异常都被捕获。您必须像以前一样管理失败的承诺,或者使用done()结束承诺链以暴露并抛出错误(请参阅the documentation)。

但是,您在setTimeout中抛出的错误与promise无关,因为错误是异步抛出的,请参阅例如this relevant question。另一种方法是拒绝这样的承诺:

function y() {
  console.log('y');
  var deferred = Q.defer();

  setTimeout(
      function() {
        console.log('throwing in y');
        deferred.reject(new Error('Oih!'));
      },
      1000
  );

  return deferred.promise;
}