我在一个在大多数代码中使用普通node.js样式回调的应用程序中使用Sequelize。 Sequelize虽然使用了promises,但是很多代码最终看起来像这样:
model.find({where: {...}}).then (res) ->
callback(null, res)
.catch (err) ->
callback(err)
大部分时间都运行良好,但是如果回调中存在问题,那么catch块将运行并再次调用回调,这次是使用err参数而不是res。
这在单元测试中尤其是一个问题,我们正在使用expect.js
,它会抛出异常并期望测试运行器捕获它们,但是它们会被sequelize catch块变得混乱,并且很难追查实际问题。
要解决这个问题,我想在当前promise的范围之外调用回调,让错误处理程序只处理与sequelize直接相关的错误。我该怎么做?
答案 0 :(得分:3)
由于sequelize使用了Bluebird的承诺,你应该可以这样做:
if (Meteor.isServer) {
Meteor.methods({
'chargeCard': function(stripeToken, amount) {
check(stripeToken, Object);
var stripe = Meteor.npmRequire('stripe')('sk_test_rand');
stripe.customers.create({
email: 'a@aol.com'
}).then(function() {
return stripe.charges.create({
amount: amount,
currency: 'gbp',
source: stripeToken.id
});
}).then(function(err, charge) {
// New charge created on a new customer
console.log(err, charge);
}, function(err) {
// Deal with an error
console.log('Card not charge')
});
}
});
}
答案 1 :(得分:0)
似乎有一些不同的解决方案。
首先,用一个更详细的例子来澄清我遇到的问题。在这里你可以看到在回调中抛出错误时会调用.catch
处理程序,这不是我想要的:
callback = (err, res) ->
console.log "Called with err: #{err} res: #{res}"
throw new Error()
models.User.find({where: {...}}).then (user) ->
callback(null, user)
.catch (err) ->
callback(err)
这是输出,您可以在其中看到两次调用回调:
Called with err: null res: [object SequelizeInstance:User]
Called with err: Error res: undefined
Unhandled rejection Error
at callback (./scripts/nodeify_test.coffee:5:15)
at [object Object].<anonymous> (./scripts/nodeify_test.coffee:10:5)
at [object Object].tryCatcher (./node_modules/sequelize/node_modules/bluebird/js/main/util.js:24:31)
at Promise._settlePromiseFromHandler (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:454:31)
at Promise._settlePromiseAt (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:530:18)
at Promise._settlePromises (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:646:14)
at Async._drainQueue (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:177:16)
at Async._drainQueues (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:187:10)
at Async.drainQueues (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:15:14)
at process._tickCallback (node.js:419:13)
.then .catch
Bergi指向When is .then(success, fail) considered an antipattern for promises?,其中给出了.then之前调用.catch的示例,我确认解决了问题:
callback = (err, res) ->
console.log "Called with err: #{err} res: #{res}"
throw new Error()
models.User.find({where: {...}}).catch (err) ->
callback(err)
.then (user) ->
callback(null, user)
这是输出:
Called with err: null res: [object SequelizeInstance:User]
Unhandled rejection Error
at callback (./scripts/nodeify_test.coffee:5:15)
at [object Object].<anonymous> (./scripts/nodeify_test.coffee:10:5)
at [object Object].tryCatcher (./node_modules/sequelize/node_modules/bluebird/js/main/util.js:24:31)
at Promise._settlePromiseFromHandler (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:454:31)
at Promise._settlePromiseAt (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:530:18)
at Promise._settlePromises (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:646:14)
at Async._drainQueue (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:177:16)
at Async._drainQueues (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:187:10)
at Async.drainQueues (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:15:14)
at process._tickCallback (node.js:419:13)
.nodeify
cassjj也指向了nodeify,它有效地将promises转换为普通的节点代码:
callback = (err, res) ->
console.log "Called with err: #{err} res: #{res}"
throw new Error()
models.User.find({where: {...}}).nodeify callback
此处输出与.catch .then
示例匹配:
Called with err: null res: [object SequelizeInstance:User]
./node_modules/sequelize/node_modules/bluebird/js/main/async.js:43
fn = function () { throw arg; };
^
Error
at [object Object].callback (./scripts/nodeify_test.coffee:5:15)
at [object Object].tryCatcher (./node_modules/sequelize/node_modules/bluebird/js/main/util.js:24:31)
at Promise.successAdapter [as _fulfillmentHandler0] (./node_modules/sequelize/node_modules/bluebird/js/main/nodeify.js:22:30)
at Promise._settlePromiseAt (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:528:21)
at Promise._settlePromises (./node_modules/sequelize/node_modules/bluebird/js/main/promise.js:646:14)
at Async._drainQueue (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:177:16)
at Async._drainQueues (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:187:10)
at Async.drainQueues (./node_modules/sequelize/node_modules/bluebird/js/main/async.js:15:14)
at process._tickCallback (node.js:419:13)
我也确认即使添加了一个catch处理程序,我也会看到相同的结果:
models.User.find({where: {...}}).nodeify callback
.catch (err) ->
callback.call({}, err)
我将选择.nodeify
。