jried
jried

Reputation: 71

Sequelize findOrCreate() -- .catch() block executed after spread() during no error

My error is similar to this post:

Using sequelize.js as an ORM handler. queryCondition variable value: {where: {$or: [{username:user.username},{email:user.email}]},defaults:user}

Problem: After successfully saving a user instance to the database, the spread() is called as recommended after invoking findOrCreate(). The function block in spread() is invoked, then immediately after the .catch() block is invoked. No clue why this is happening. Can someone please help?

 model.User.findOrCreate(queryCondition).spread(function(user, created){
    callback && callback(user, created);
 }).catch(function(error){
     callback && callback(null, null, error);
 });

Upvotes: 1

Views: 3503

Answers (2)

jried
jried

Reputation: 71

Found the answer: Sequelize uses Bluebird.js as it's promise library (check out the package.json file). The documentation explains the spread() method, which is recommended to use in sequelize 3.0 (see post). A section in this document states that spread() invokes all().then(..) under the covers. Therefore, the following change solved my problem using Node.js:

model.User.findOrCreate(queryCondition) .all().then(function(result, isCreated){ callback && callback(null, result, isCreated); }, function(error) { callback && callback(error); });

Properly resolved promises do not fall into the error block, and actual database errors are caught in the error block. Finally, for those who assumed the error was due to the callback arguments, note that I simply reordered the callback arguments given num8er's suggestion below. :) Hope this helps someone else.

Upvotes: 4

num8er
num8er

Reputation: 19372

If it's invoking .catch block so it seems to have some issue.

Try to debug it and see the reason:

 model.User.findOrCreate(queryCondition).spread(function(user, created){
   callback && callback(user, created);
 }).catch(function(error){
   console.error(queryCondition, error); // add this and check the output
   callback && callback(null, null, error);
 });

also I saw that Your queryCondition variable is also ok.

{
  where:{$or: [{username:user.username},{email:user.email}]},
  defaults:user
}

so let's try this annotation:

{
  where:{$or: [{username: {$eq: user.username}},{email: {$eq: user.email}}]},
  defaults:user
} 

read this: http://docs.sequelizejs.com/en/latest/docs/querying/#where

and if with another annotation it will not work properly so I can recommend You to check Your table columns for null, not null fields and compare it with user object to see if there is missing field in user object.


after reading Bergi's comment I'll also recommend You to try to do it like this:

 model.User
   .findOrCreate(queryCondition)
   .then(
     function(result, isCreated){
       callback && callback(result, isCreated);
     },
     function(error) {
       callback && callback(null, null, error);
     });




In case of spread method I think it does not throw exception to be catchable, so in this case:

model.User
  .findOrCreate(queryCondition)
  .spread(function(result, isCreated){
    if(!result) {
      return callback && callback('Cannot create user');
    }
    callback && callback(null, result, isCreated);
  });




P.S. Usually in most of packages it's convention to return error as first argument of callback. So I can only guess that problem happens not in Your code example, it happens somewhere outside that waits for callback.

So try to modify callback like this:

callback(user, created);  =>  callback(null, user, created);

callback(null, null, error);  =>  callback(error);

Upvotes: 2

Related Questions