繁体   English   中英

NodeJS最佳实践:流量控制的错误?

[英]NodeJS best practices: Errors for flow control?

在Node.js中,我应该使用错误进行流量控制,还是应该像异常一样使用它们?

我正在Sails.js中编写一个身份验证控制器和一些单元测试,目前,我的注册方法检查是否存在具有相同用户名的用户。 如果用户已经存在用户名,我的模型方法会使用新的Error对象调用其回调参数,如下所示:

模型:

exists: function (options, cb) {
    User.findOne({
        where: { username: typeof options === 'Object' && options.username ? options.username : options },
    }).exec(function (err, user) {
        if (err) return cb(err);
        if (user) return cb(new Error("A user with that username already exists."));
        cb(null, !!user);
    });
},

控制器:

User.exists(req.body.user.username, function (err, exists) {
  if (err) {
    console.log("error: ", err);
    return res.status(409).json({
      message: err
    });      
  }

  User.create(req.user).then(function (data) {
    res.status(201).json({
      user: data
    });
  });
});

这是最佳做法吗? 我不确定节点约定是否支持异常情况或流量控制的错误。 我想我应该改写这个,但是在我这样做之前我想知道惯例。 我想我已经在Sails中看到过这样写的一些例子。 谢谢!

通过使用关键字throw Node(或Javascript)可以在异常上抛出错误:

if (something_went_wrong) {
  throw new Error('Doh!');
}

您还可以向默认的Error对象添加其他参数,以便为程序中的错误提供更多语义含义。 话虽如此,您不希望在路由处理程序中抛出错误,因为这会使进程和服务器崩溃。

在Sails中使用路由处理程序(或真正表达)时,您当然应该检查错误类型并相应地响应客户端。

// -- Route handler
app.get('/something', function (req, res, next) {

  DB.create({ username: 'user' }, function (err, docs) {

    if (err) {

      // This checks to see if we have a unique error from MongoDB
      // and send the appropriate response to the client
      if (err.code === 11000 || error.code === 11001) {
        return res.send(409); // or return res.json(409, {message: "User exists"});
      }

      // Any other error type is assumed to be an internal error so we pass it
      // down the chain to the error handler middleware
      return next(err);

    }

    // This is a client error, not an internal error so we respond to the client
    // with the appropriate client error type
    if (docs.length === 0) return res.send(404);

    if (user.notAuthorized) return res.send(403);

    res.send('All Good');

  });

});

请注意,在DB响应内部错误的情况下,我们将传递给next()函数,该函数由链中的错误处理中间件拾取。 任何精度为4的中间件都被定义为错误处理中间件。 Sails可能有一些默认的错误处理程序,但您也可以覆盖它 - 您需要检查相应的文档以获取此信息,因为我更喜欢单独使用Express获得的控件。

以上答案适用于Express,但在Sails控制器中你不应该打电话给next ; 最佳做法是始终返回响应。 在大多数示例Sails代码中,您甚至不会将next作为控制器动作函数的参数。 另请注意,Sails附带了一些内置于res对象的默认响应方法 ,例如res.serverErrorres.badRequest ,以及res.negotiate ,它将根据状态尝试将错误路由到适当的处理程序码。 所以你的例子可以调整为:

模型:

exists: function (options, cb) {
    User.findOne({
        where: { username: typeof options === 'Object' && options.username ? options.username : options },
    }).exec(function (err, user) {
        // res.negotiate will default to a 500 server error
        if (err) return cb(err);
        // res.negotiate will just output the status code and error object
        // as JSON for codes between 400 and 500, unless you 
        // provide a custom view as api/responses/badRequest.ejs
        if (user) return cb({
          status: 409, 
          message: "A user with that username already exists."
        });
        cb(null, !!user);
    });
},

控制器:

User.exists(req.body.user.username, function (err, exists) {
  // Let Sails handle those errors for you
  if (err) {return res.negotiate(err);}

  User.create(req.user).then(function (data) {
    res.status(201).json({
      user: data
    });
  });
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM