Skip to content Skip to sidebar Skip to footer

Problems With Sequelize Promises And Normal Node.js Callbacks

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

Solution 1:

Since sequelize uses Bluebird promises, you should be able to do this:

model.find({where: {...}).nodeify(callback);

Solution 2:

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

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}"thrownew 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:

Calledwitherr: nullres: [objectSequelizeInstance:User]
Calledwitherr: Errorres: undefinedUnhandled rejection Error
  at callback (./scripts/nodeify_test.coffee:5:15)
  at [objectObject].<anonymous> (./scripts/nodeify_test.coffee:10:5)
  at [objectObject].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)

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}"thrownew Error()

models.User.find({where: {...}}).catch (err) ->
    callback(err)
.then (user) ->
    callback(null, user)

Here's the output:

Calledwitherr: nullres: [objectSequelizeInstance:User]
Unhandled rejection Error
  at callback (./scripts/nodeify_test.coffee:5:15)
  at [objectObject].<anonymous> (./scripts/nodeify_test.coffee:10:5)
  at [objectObject].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)

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}"thrownewError()

models.User.find({where: {...}}).nodeify callback

Here the output matches the .catch .then example:

Calledwitherr: nullres: [objectSequelizeInstance:User]

./node_modules/sequelize/node_modules/bluebird/js/main/async.js:43
        fn = function () { throw arg; };
                                 ^
Error
  at [objectObject].callback (./scripts/nodeify_test.coffee:5:15)
  at [objectObject].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)

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)

I'm going to go with .nodeify.

Post a Comment for "Problems With Sequelize Promises And Normal Node.js Callbacks"