chornbe
chornbe

Reputation: 1163

Node and sequelize -> .catch(...) isn't working as expected

I've got a really simple example here. In this case, 'token' is a read-only property on the model, and throws an error when you try to write it. This is just present to force an error to show how .catch(...) isn't ever being called. The very simple example code is below (name, description, uptime are all variables set to static values before we get to this code):

models.TANServer.create({
    name : name,
    description : description,
    defaultUpTime : defaultUpTime,
    token : "apple"
})
.then( function( server ){

    if( !server ){
        res.statusCode = 400;
        res.end( "unknown error creating new server entry" );
        return;
    }

    res.statusCode = 200;
    res.end( JSON.stringify( server ) );
    return;

}).catch( function( reason ){
    res.statusCode = 500;
    res.end( "This should print out " + reason + " but is never called as the error stack goes to console, and nothing ever is caught." );
    return;
});

The catch is never called, the http request just sits there spinning, and the console output pretty clearly displays that the exception just bubbled up without being caught.

What am I missing about .catch(...) in Sequelize calls?

Thanks.

The pertinent info from the exception stack output follows. The text "This is a read only property" is the error message I generate and toss when you try to write to that property.

Unhandled rejection Error: This is a read-only property

Upvotes: 4

Views: 4562

Answers (1)

Sean Vieira
Sean Vieira

Reputation: 159995

The issue is that .catch only catches issues thrown in the promise resolution handler (that is, the function passed to .then in your example).

Looking at the comments, it appears that the line throwing the error is:

models.TANServer.create({
  name : name,
  description : description,
  defaultUpTime : defaultUpTime,
  token : "apple"
})

If that is the case, then no promise is returned, and so the .then and .catch expressions are never run, and no response is returned.

The fix is to change .create so it returns a failed promise (using Promise.reject) rather than throwing an error

What if I can't fix .create?

If .create is third-party code, or if you need synchronous errors most of the time, but this one case is painful you can wrap the call to create in a try / catch statement or a Promise.resolve block:

try {
  models.TANServer.create(...).then(...).catch(...);
catch (e) {
  // A synchronous exception happened here
}

// Alternatively (and much better IMO):
Promise.resolve().then(() => {
  // Any synchronous errors here will fail the promise chain
  // triggering the .catch
  return models.TANServer.create(...);
}).then(server => {
  // Use server here
}).catch(reason => {
  // All errors show up here
});

Upvotes: 4

Related Questions