Sequelize findOrCreate() -- .catch() 块在没有错误期间在 spread() 之后执行

Posted

技术标签:

【中文标题】Sequelize findOrCreate() -- .catch() 块在没有错误期间在 spread() 之后执行【英文标题】:Sequelize findOrCreate() -- .catch() block executed after spread() during no error 【发布时间】:2016-09-06 21:28:26 【问题描述】:

我的错误类似于这个post:

使用 sequelize.js 作为 ORM 处理程序。 queryCondition 变量值:where: $or: [username:user.username,email:user.email],defaults:user

问题:成功将用户实例保存到数据库后,调用findOrCreate() 后按推荐调用spread()spread() 中的功能块被调用,然后在.catch() 块被调用之后立即被调用。不知道为什么会这样。有人可以帮忙吗?

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

【问题讨论】:

您可以在您的问题中输入 queryCondition 变量吗? where: $or: [username:user.username, email:user.email],defaults:user 听起来您的callback 确实引发了异常。 error 是什么? 对于此类情况,您需要使用then(onFulfilled, onRejected) pattern 而不是.then(…).catch(…)。或者,鉴于 Sequelize 使用 Bluebird,请查看 asCallback(尽管它使用节点回调约定,而不是您的自定义参数顺序)。 没有错误。数据插入成功,但 .catch() 块在之后立即执行 【参考方案1】:

找到答案: Sequelize 使用 Bluebird.js 作为它的 promise 库(查看 package.json 文件)。 documentation 解释了 spread() 方法,推荐在 sequelize 3.0 中使用(参见 post)。本文档中的一个部分指出,spread() 在幕后调用 all().then(..)。因此,以下更改使用 Node.js 解决了我的问题:

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

正确解析的 Promise 不会落入错误块中,并且实际的数据库错误会被捕获在错误块中。最后,对于那些认为错误是由于回调参数引起的人,请注意,我只是根据下面 num8er 的建议对回调参数进行了重新排序。 :) 希望这对其他人有所帮助。

【讨论】:

您现在使用三个参数调用callback,而不是像您在原始问题中那样使用两个参数。我的猜测是 that 实际上解决了您的问题,而不是重写为.all().then()。在您的初始代码中,回调很可能引发异常(如@Bergi 建议的那样),因为它认为发生了错误,这就是触发catch 的原因(我假设回调执行if (err) throw err 或类似的东西)。 我根据下面 num8er 的建议切换了我的 callback() 的参数顺序以匹配约定...切换参数不是我的错误的原因。【参考方案2】:

如果它正在调用.catch 块,那么它似乎有一些问题。

尝试调试一下,看看原因:

 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);
 );

我还看到您的 queryCondition 变量也可以。


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

让我们试试这个注解:


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

阅读:http://docs.sequelizejs.com/en/latest/docs/querying/#where

如果使用另一个注释,它将无法正常工作,因此我建议您检查表列中的 nullnot null 字段并将其与 user 对象进行比较,以查看 @987654329 中是否缺少字段@ 目的。 在阅读了 Bergi 的评论后,我也建议您尝试这样做:

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

如果是spread 方法,我认为它不会抛出可捕获的异常,所以在这种情况下:

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

附:通常在大多数包中,将错误作为回调的第一个参数返回是惯例。所以我只能猜测这个问题不会发生在你的代码示例中,它发生在等待回调的某个地方。

所以尝试像这样修改回调:

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

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

【讨论】:

感谢您的订购建议。我一定会重构...我还添加了查询条件 JSON 变量。 @jried 我已经更新了我的答案,请检查您的表格列是否有关于必填字段的约束,我可以猜测您的用户对象中没有一些非空字段 尝试了两件事:1.添加第三个参数 .spread(function(error, user, created) ... 然后打印变量内容:Spread返回的变量只有两个。2.删除.catch() 语句,如果实际上插入数据时出错,这会导致异常本质上,findOrCreate 成功插入数据,然后我将对象取回......由于某种原因,在成功解析后仍会立即调用 .catch()。 @jried 我没有更改传播参数 ))) 再次你可以在 catch 块内执行 console.log(error) 吗? @jried 我已经更新了我的答案并添加了 Bergi 的提议,试试吧。

以上是关于Sequelize findOrCreate() -- .catch() 块在没有错误期间在 spread() 之后执行的主要内容,如果未能解决你的问题,请参考以下文章

Sequelize findOrCreate() -- .catch() 块在没有错误期间在 spread() 之后执行

续集 findOrCreate 插入新行但返回未定义主键的对象

Node.js学习10~Sequelize基本sql学习

在 Sequelize 中使用 .create(...) 方法时如何处理错误

Node.js学习13~基于node-sequelize的查询器,附代码举例

Sails.js Waterline ORM:.findOrCreate() 没有 .populate() 方法