处理promisses和服务器响应的正确方法

时间:2016-09-23 12:42:27

标签: node.js promise sails.js

我正在尝试改进我在node.js / sail.js中的代码,我正在与promisses中的服务器响应作斗争。

当您查看第一个.then函数时,如果falseforbidden access,您可以看到该方法返回notFound。然后,在接下来的.then函数中,我必须检查返回类型是否为=== false以跳过部分并避免两次发送http标头。可以以某种方式改进,以便在发生故障时跳过所有下一个.then方法吗?我可以在最后.catch中抛出异常,但必须有case在所有可能的状态之间切换。 (即禁止,serverError甚至找不到)

Notification.findOne({id: req.param('id')})
  .then(function(notification) {
    if (!notification) {
      res.notFound();
      return false;
    }

    if (notification.triggeredBy != req.session.user.id) {
      res.forbidden();
      return false;
    }

    return notification;
  })
  .then(function(notification) {
    if (notification === false) {
      return false;
    }

    return Notification.update(notification.id, actionUtil.parseValues(req));
  })
  .then(function(notification) {
    if (notification === false) {
      return false;
    }

    res.json(notification);
  })
  .catch(function(err) {
    sails.log(err);
    res.serverError({message: 'A server error occurred.'});
  })

2 个答案:

答案 0 :(得分:2)

如果我这样做,首先我分离逻辑和接收/发送功能。其次,我指定了错误代码列表。就像那样:

NotificationService.js

/*
 Listing of error codes: {
  * [1] Object not found
  * [2] Forbidden
  * [3] Server error
 }
 */
module.exports = {
    nameOfMethod: function(ID, sessionID) {

        return new Promise(function(resolve, reject) {
            Notification.findOne({ id: ID })
                .then(function(notification) {
                    if (!notification) return reject({ error_code: 1 });
                    if (notification.triggeredBy !== sessionID) return reject({ error_code: 2 });

                    Notification.update(notification.id, actionUtil.parseValues(req))
                        .then(function(notification) {
                            return resolve(notification); // finally return our notification
                        })
                        .catch(function(err) {
                            sails.log.error(err); // It's good when log is classified. In this case is error
                            return reject({ message: 'A server error occurred.' }); 
                        });
                })
                .catch(function(err) {
                    sails.log.error(err);
                    return reject({ message: 'A server error occurred.' });
                });
        });
    }
};

NotificationController.js

module.exports = {
  notifyMe: function(req, res) {
    const ID = req.param('id'), sessionID = req.session.user.id;

    NotificationService.nameOfMethod(ID, sessionID)
      .then(function(notification) {
        return res.send(notification);
      })
      .catch(function(err) {
        switch (err.error_code) {
          case 1:
            return res.notFound(err);

          case 2:
            return res.forbidden(err);

          default:
            return res.serverError(err);
        }
      });
  }
};

如果我使用开关,我认为选择正确的响应是更好的方法,但这次我没有任何想法

答案 1 :(得分:1)

了解如何在Bluebird中实现过滤的.catch() - 在您的情况下,抛出所需的所有错误但避免在catch处理程序中使用大的开关/案例块非常有用:

.catch(
    class ErrorClass|function(any error)|Object predicate...,
    function(any error) handler
) -> Promise
.caught(
    class ErrorClass|function(any error)|Object predicate...,
    function(any error) handler
) -> Promise
  

这是.catch的扩展,更像是catch-clauses   Java或C#等语言。而不是手动检查instanceof或   .name ===" SomeError",您可以指定一些错误构造函数   哪个符合此捕获处理程序的条件。捕获处理程序是   第一次遇到有指定的合格构造函数,就是那个   将被召唤。

示例:

somePromise.then(function() {
    return a.b.c.d();
}).catch(TypeError, function(e) {
    //If it is a TypeError, will end up here because
    //it is a type error to reference property of undefined
}).catch(ReferenceError, function(e) {
    //Will end up here if a was never declared at all
}).catch(function(e) {
    //Generic catch-the rest, error wasn't TypeError nor
    //ReferenceError
});

请参阅:http://bluebirdjs.com/docs/api/catch.html#filtered-catch

而不是:

return false;

你可以使用:

return Promise.reject(someReason);

或:

throw someReason;

并且您不必检查这些false值 - 只需使用(可能是多个)catch个处理程序。