【问题标题】:Sequelize findOrCreate() -- .catch() block executed after spread() during no errorSequelize findOrCreate() -- .catch() 块在没有错误期间在 spread() 之后执行
【发布时间】: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() 块在之后立即执行

标签: javascript node.js sequelize.js


【解决方案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 的提议,试试吧。
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-03
  • 1970-01-01
  • 2018-07-21
  • 2016-04-12
  • 2014-07-16
  • 1970-01-01
相关资源
最近更新 更多