Sequelize Promise和正常的node.js回调问题 [英] Problems with Sequelize promises and normal node.js callbacks

查看:64
本文介绍了Sequelize Promise和正常的node.js回调问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在大多数代码中使用普通node.js样式回调的应用程序中使用Sequelize.尽管Sequelize使用了promises,所以很多代码最终看起来像这样:

I'm using Sequelize in an application that uses normal node.js style callbacks in most of its code. Sequelize uses promises though, so a lot of code ends up looking something like this:

model.find({where: {...}}).then (res) ->
    callback(null, res)
.catch (err) ->
    callback(err)

在大多数情况下,效果很好,但是如果回调中存在问题,则catch块将运行并第二次调用回调,这一次使用err参数而不是res.

That works well most of the time, but if there's a problem within the callback then the catch block will run and invoke the callback a second time, this time with the err argument instead of res.

在使用expect.js的单元测试中,这尤其是个问题,它会引发异常并期望测试运行程序能够捕获异常,但相反,它们由于混乱的catch块而变得混乱,从而难以追踪实际的问题.

This is particularly a problem in unit test where we're using expect.js, which throws exceptions and expects the test runner to catch them, but instead they're getting garbled by sequelize catch blocks and making it difficult to track down the actual problem.

为解决此问题,我想在当前Promise范围之外调用回调,并让错误处理程序只处理与序列化直接相关的错误.我该怎么办?

To solve this problem I'd like to invoke the callback outside of the scope of the current promise, and have the error handler only ever deal with errors directly related to sequelize. How do I do this?

推荐答案

似乎有一些不同的解决方案.

It seems that there are a few different solutions to this.

首先,通过更详细的示例来阐明我遇到的问题.在这里,您可以看到.catch处理程序在回调中引发错误时被调用,这不是我想要的:

First, to clarify the problem I was having with a more detailed example. Here you can see that the .catch handler gets invoked when the error is thrown in the callback, which isn't what I wanted:

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)

以下是输出,您可以在其中看到回调被调用两次:

Here's the output, where you can see the callback getting invoked twice:

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 指向何时.then(成功,失败)被认为是反模式给出了在.then之前调用.catch的示例,我确认可以解决此问题:

Changing the order of .then .catch

Bergi pointed to When is .then(success, fail) considered an antipattern for promises? which gives the example of calling .catch before .then, and I confirmed that solves the problem:

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,它有效地将诺言变成了普通的节点代码:

Using .nodeify

cassjj also pointed to nodeify, which effectively turns the promises into normal node code:

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处理程序,我也会看到相同的结果:

I also confirmed that I see the same result even if I add a catch handler:

 models.User.find({where: {...}}).nodeify callback
.catch (err) ->
    callback.call({}, err)

我要和.nodeify一起去.

这篇关于Sequelize Promise和正常的node.js回调问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆