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

我的印象是,承诺内的exception会触发后续的失败处理程序,但在这段代码中看不到它发生:

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'); } ); 

我做错了什么,还是我误解了?

你正在混合callback和承诺+你有一个延迟反模式的情况。 要么使用Q.delay或者像下面这样的包装器:

 function delay(ms) { var d = Q.defer(); setTimeout(d.resolve, ms); return d.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'); }); 

承诺链中的所有exception都被捕获。 您必须像以前一样pipe理失败的承诺,或者使用done()结束承诺链,以公开并抛出错误(请参阅文档 )。

然而,你抛出setTimeout的错误与承诺无关,因为错误是asynchronous抛出的,请参阅这个相关的问题 。 另一种方法是拒绝这样的承诺:

 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; }