Controller Recovery with Node 7 Async / Await

Let's look at the Restify example below, which now includes support for / w630> 7 / 8s.

I have a little concern about the proper implementation of this in express / restify / etc. My concern is that the promise hangs in the event loop longer than necessary ... I know this is not quite a promise, but should I be concerned about this implementation? I have not noticed any problems yet.

'use strict'; const restify = require('restify'); const User = require('./models/User'); const server = restify.createServer({ name: 'myapp', version: '1.0.0' }); server.use(restify.acceptParser(server.acceptable)); server.use(restify.queryParser()); server.use(restify.bodyParser()); server.get('/echo/:name', async function (req, res, next) { try { const user = await User.findOne({ name: req.params.name; }); res.send(user.get({plain: true})); } catch (error) { console.error(error); res.send(500); } return next(); }); server.listen(8080, function () { console.log('%s listening at %s', server.name, server.url); }); 
+5
source share
1 answer

There is a problem using the async function instead of the usual functions that receive callbacks, because errors are handled differently.

In callback functions (for example, "err-backs"), the callback must be called independently if the execution was successful. The first parameter must be an error object.

The async function simply returns a rejected promise in case of any error (synchronous or asynchronous).

Thus, by default, Express.js / Restify expects a regular return. And if you pass the async function and fail, Express.js / Restify will continue to wait for the callback, ignoring the rejected promise. He simply does not know about the returned promise and does not address him. Finally, the callback will not be called at all, and the endpoint will be timed out.

Therefore, you cannot handle the error correctly.

You can try:

 server.get('/echo/:name', async function (req, res, next) { throw new Error(); }); 

So, as a rule, I would recommend not mixing concepts and never passing callbacks to async functions. This is a red flag.

To fix this, you need to use a shell like this:

 const wrap = function(fn) { return function(req, res, next) { return fn(req, res, next).catch(function(err) { return next(err); }); }; }; server.get('/echo/:name', wrap(async function (req, res, next) { throw new Error(); })); 

You will receive the correct status code and there will no longer be a timeout.

There are also several modules that you can use if you do not want to wrap them yourself:

0
source

Source: https://habr.com/ru/post/1266929/


All Articles