
Product
Socket Brings Supply Chain Security to skills.sh
Socket is now scanning AI agent skills across multiple languages and ecosystems, detecting malicious behavior before developers install, starting with skills.sh's 60,000+ skills.
@root/async-router
Advanced tools
A lightweight, zero-dependency JavaScript library to bring native Promises and
async/await to Express.
Wraps the Express Router and provides a drop-in replacement to allow you to progressively enhance your routes with Promise and await support.
// Handle Async & Promise routes - and normal routes too!
app.get('/foo', async function (req, res) {
// no more try/catch wrappers
// no more 'unhandledRejection' errors
let user = await UserService.findById(req.user.id);
res.json(users);
});
express.Router()
Promisesasync/awaitunhandledPromiseRejectionWarningunhandledRejectionres.json() can be called automaticallySwap out app for a the async router, and handle the server separately:
let app = require('@root/async-router').Router();
// ...
let server = express().use('/', app);
http.createServer(server).listen(3000, onListen);
Keep existing routes just they way they are...
// yuck!
app.get('/profile', async function (req, res, next) {
try {
let results = await ProfileModel.get(req.user.id);
res.json(results);
} catch(e) {
return next(e);
}
})
Or give them a facelift:
// yay!
app.get('/profile', async function (req, res) {
res.json(await ProfileModel.get(req.user.id));
})
If you need to set express options, you'll move that down to the bottom as well:
let app = require('@root/async-router').Router();
// ...
let server = express()
.use('trust proxy', 1)
.use('view engine', 'pug')
.use('/', app);
http.createServer(server).listen(3000, onListen);
Also, if you do happen to have a few routes that explicitly
res.json() in a callback after having returning a value,
those would need to be updated - a very rare case, but I'm
sure it exists in some code somewhere.
'use strict';
let http = require('http');
let express = require('express');
let app = require('@root/async-router').Router();
// Handle Async & Promise routes
app.get('/foo', async function (req, res) {
let user = await UserService.findById();
if (!user) {
throw new Error('User not found');
}
// Note: if you return a value,
// res.json() will be called automatically
// (however, just because you can doesn't mean you should)
return users;
});
// Handles existing routes too - no refactoring required!
app.get('/foo', async function (req, res) {
try {
let user = await UserService.findById();
} catch (e) {
console.error('Unexpected');
console.error(e);
res.statusCode = 500;
res.end('Internal Server Error');
}
if (!user) {
res.statusCode = 404;
res.json({ error: 'User not found' });
return;
}
res.json(users);
});
// Handle errors (must come after associated routes)
app.use('/', function (err, req, res, next) {
console.error('Unhandled Error');
console.error(err);
res.statusCode = 500;
res.end(err.message);
});
// Start node.js express server
let server = express().use('/', app);
http.createServer(server).listen(3000, function () {
console.info('Listening on', this.address());
});
Also, since it's useful to have this snippet for demos:
async function sleep(ms) {
await new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
let app = require('@root/async-router').Router();
This is just a wrapper around express.Router(), which is what provides the
default router and "mini apps" of express - so it has all of the same methods
and function signatures:
app.use(path, middlewares);
app.route(path, minApp);
app.head(path, fns);
app.get(path, fns);
app.post(path, fns);
app.patch(path, fns);
app.delete(path, fns);
// ... etc
Any incompatibility should be file as a bug.
It does NOT copy the top-level express server API. You should still use express for that:
// top-level options are still handled by the express server instance
let server = express()
.set('trust proxy', 1)
.set('view engine', 'pug')
.use('/', app);
require('http')
.createServer(server)
.listen(3000, onListen);
function onListen() {
console.info('Listening on', this.address());
}
The wrap(app) is the best way to add async/await
support to your Express app or Router.
let syncApp = express.Router();
let app = require('@root/async-router').wrap(syncApp);
Fork of express-promisify-router to bugfix error handling.
MIT License
See LICENSE.
FAQs
Write Express middleware and route handlers using async/await
We found that @root/async-router demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket is now scanning AI agent skills across multiple languages and ecosystems, detecting malicious behavior before developers install, starting with skills.sh's 60,000+ skills.

Product
Socket now supports PHP with full Composer and Packagist integration, enabling developers to search packages, generate SBOMs, and protect their PHP dependencies from supply chain threats.

Security News
An AI agent is merging PRs into major OSS projects and cold-emailing maintainers to drum up more work.