如何使用promise在express.js中正确处理错误(string或对象)
我不是在我的第一个express.js应用程序,但我仍然找出最强大的方法来处理错误。
由于io.js是几个月的现实,我使用原生Promise来帮助自己asynchronous,下面的代码反映了这一点。
我的error handling中间件如下:
router.use(function (err, req, res, next) { // in case err.custom is present, means is an "handled" Error, created by developers if (!!err.custom) { return res.status(err.code).json(err.message); } if (err instanceof Error) { console.error(err.stack); return res.status(500).send('Runtime Error'); // should be reported! } // last but not least, validation error res.status(400).send(err); });
一个示例控制器是这样写的:
function callService1 (param1) { return new Promise(function (resolve, reject) { service.call(param1, function (err, data) { if (!!err) return reject(err); // this is an Error object?? not sure! if (!!data.handledError) { // this is an handled Error to the user, not 500 return reject({ custom: true, status: 403, message: 'service1 tells you that myCoolParam is not valid' }); } resolve(data); }); }; } function callService2 (dataFromParam1) { return new Promise(function (resolve, reject) { // something here }); } // this is the API "controller" module.exports = function (req, res, next) { callService1(req.body.myCoolParam) .then(callService2) .then(function (service2Output) { res.status(200).json({ message: 'everything went smooth!' }); }) .catch(next); // here is the catch-all errors };
正如你所看到的快递中间件看起来相当整齐和优雅。
我通常在rejects()
把所有有趣的error handling给用户,其中一些被我们告诉error handling中间件的对象调用。
问题是来自示例的service
是第三方库。 这些库有时会返回一个string,有时候是一个对象(来自外部的API),有时候是一个javascript错误。
目前我不能处理自定义JavaScript对象,而且如果我想抛出一个错误500的用户,我必须reject(new Error(err));
但有时这个err
是一个对象,导致:
Error: [object Object] at errorHandler (awesomeapi\postsomething.js:123:16) at IncomingMessage.<anonymous> (node_modules\mandrill-api\mandrill.js:83:24) at emitNone (events.js:72:20) at IncomingMessage.emit (events.js:163:7) at _stream_readable.js:891:16 at process._tickCallback (node.js:337:11)
这并不酷,我真的很想找出一种方法来处理这些错误,而不添加代码(如果可能的话),因为我觉得这个语法非常优雅和简洁。
我想了很多关于这个问题,我最终创build/使用这个https://github.com/yzarubin/x-error/blob/master/lib/x-error.js这是一个自定义的服务器端错误对象,inheritance错误,并扩展function来处理http代码和响应。
把它应用到你的案例中,我会这样做:
function callService1 (param1) { return new Promise(function (resolve, reject) { service.call(param1, function (err, data) { if (!!err) return reject(new xError().extend(err).setHttpCode(500)); // This will inherit the original stack & message if (!!data.handledError) { return reject(new xError('this is an handled Error to the user, not 500').setHttpCode(403)); } resolve(data); }); }; }
然后在你的控制器中,你可以检查instanceof xError === true并处理它,否则做一些默认的响应。 但是我也在应用程序中做了这样的事情,在这个应用程序中,每个承诺最终都会解决或拒绝xError的一个实例:
router.use(function (err, req, res, next) { res.status(err.httpCode || 500).send(err.message || 'Internal error'); });
- 谷歌oauth不返回电子邮件通行证authentication
- events.js:130 throw TypeError('listener must be a function')
- 如何让我的Express应用程序尊重上传的Orientation EXIF数据?
- 表示js – socket io连接
- 快速API res.jsonp返回双重callback
- 如何dynamic地决定请求是否应该通过Express中间件
- 如何获取通过sails.js中的窗体发送的数组/对象(使用enctype multipart / form-data)
- 如何在AfterCreate中访问请求对象 – waterline,sails
- 回环与i18n支持