如何尽早打破承诺链,在Express中发送错误?

我有这个请求处理程序,它看起来像这样:

router.post('/', function(req,res) { var screencast; var channel; youtube.get(req.body.videoId).then(function(data) { screencast = data.screencast; channel = data.channel; }).then(function() { return connection.beginTransactionAsync(); }).then(function() { return connection.queryAsync('INSERT IGNORE INTO Channels SET ?', channel); }).then(function() { return connection.queryAsync('INSERT INTO Screencasts SET ?', screencast) }).then(function() { return connection.commit(); }).error(function(e) { connection.rollback(); }); }); 

有时我想尽早打破承诺链,并发出错误。 这是我试过的:

 router.post('/', function(req,res) { var screencast; var channel; youtube.get(req.body.videoId).then(function(data) { if (data === null) { res.send('error: video does not exist.'); return; } screencast = data.screencast; channel = data.channel; }).then(function() { console.log('trace: starting transaction'); return connection.beginTransactionAsync(); }).then(function() { return connection.queryAsync('INSERT IGNORE INTO Channels SET ?', channel); }).then(function() { return connection.queryAsync('INSERT INTO Screencasts SET ?', screencast) }).then(function() { return connection.commit(); }).error(function(e) { connection.rollback(); }); }); 

虽然错误显示,承诺链明显不会中断; 下一个函数被调用。

我的问题是, 如何及早打破承诺链发送错误?

我试过的东西是引入更多级别的缩进:

 youtube.get(req.body.videoId).then(function(data) { if (data === null) { res.send('error: video does not exist.'); return; } connection.beginTransactionAsync().then(function() { return connection.queryAsync('INSERT IGNORE INTO Channels SET ?', channel); }).then(... 

我发现这个工作, 但是我担心使用更多的嵌套,因为我还需要检查video是否已经存储在数据库中处理之前,需要两个级别的缩进,也许更多。

我发现了另外两个答案( 其中一个 ),但是他们对我没有帮助。 我的问题特别与Bluebird和Express有关。

我想你只需要添加一个.catchcallback到你的承诺链,并throw一个问题,应该摆脱承诺。

 router.post('/', function(req,res) { var screencast; var channel; youtube.get(req.body.videoId).then(function(data) { if (data === null) { throw new Error('video does not exist.'); } screencast = data.screencast; channel = data.channel; }).then(function() { console.log('trace: starting transaction'); return connection.beginTransactionAsync(); }).then(function() { return connection.queryAsync('INSERT IGNORE INTO Channels SET ?', channel); }).then(function() { return connection.queryAsync('INSERT INTO Screencasts SET ?', screencast) }).then(function() { return connection.commit(); }).error(function(e) { connection.rollback(); }).catch(function(err){ res.send("error: " + err); }); });