Passing in Async functions to Node.js Express.js router
May be you didn't found results because async/await
is an ES7 not ES6 feature, it is available in node >= 7.6.
Your code will work in node. I have tested the following code
var express = require('express');
var app = express();
async function wait (ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms)
});
}
app.get('/', async function(req, res){
console.log('before wait', new Date());
await wait(5 * 1000);
console.log('after wait', new Date())
res.send('hello world');
});
app.listen(3000, err => console.log(err ? "Error listening" : "Listening"))
And voila
MacJamal:messialltimegoals dev$ node test.js
Listening undefined
before wait 2017-06-28T22:32:34.829Z
after wait 2017-06-28T22:32:39.852Z
^C
Basicaly you got it, you have to async
a function in order to await
on a promise inside its code.
This is not supported in node LTS v6, so may be use babel to transpile code.
Hope this helps.
Update
Since ExpressJs 5, async functions are supported, and throw errors as expected
Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error
source
In Express 4 or less, it sort of works, but not really
While it seems to work, it stops handling errors thrown inside the async function, and as a result, if an error is not handled, the server never responds and the client keeps waiting until it timeout.
The correct behavior should be to respond with a 500 status code.
Solutions
express-promise-router
const router = require('express-promise-router')();
// Use it like a normal router, it will handle async functions
express-asyncify
const asyncify = require('express-asyncify')
To fix routes set in the app
object
Replace var app = express();
with
var app = asyncify(express());
To fix routes set in router
objects
Replace var router = express.Router();
with
var router = asyncify(express.Router());
Note
You only need to apply the asyncify
function in the objects where you set the routes directly
https://www.npmjs.com/package/express-asyncify
I think you can't do it directly because exceptions are not caught and the function won't return if one is thrown. This article explains how to create a wrapper function to make it work: http://thecodebarbarian.com/using-async-await-with-mocha-express-and-mongoose.html
I haven't tried it but was investigating this recently.
Use express-promise-router.
const express = require('express');
const Router = require('express-promise-router');
const router = new Router();
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'localhost',
user: 'myusername',
password: 'mypassword',
database: 'mydb',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
}).promise();
router.get('/some_path', async function(req, res, next) {
const [rows, ] = await pool.execute(
'SELECT * ' +
'FROM mytable ',
[]
);
res.json(rows);
});
module.exports = router;
(The above is an example of using mysql2's promise interface with express-promise-router
.)