JSPM

@phoenix35/express-async-methods

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q18595F
  • License MPL-2.0

Augments express with Async methods

Package Exports

  • @phoenix35/express-async-methods

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@phoenix35/express-async-methods) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@phoenix35/express-async-methods

My own take at making express compatible with async functions.
Heavily inspired by @awaitjs/express and @root/async-router.

Most credits go to them.

How to use

addAsync

addAsync(
  app[, methods ]
);

The default methods that this adds support to

methods = [ "use", "delete", "get", "head", "param", "patch", "post", "put" ]

If you don't use a router, wrap your express app with this.

const express = require("express");
const { addAsync } = require("@phoenix35/express-async-methods");

const app = addAsync(express());

// Supports error-handling middleware
app.useAsync(async (err, req, res, next) => {
  await asyncLog(err.stack);

  res.status(500).send("Something broke!");
});

// Supports any routing
app.getAsync("/users/:userId", async (req, res) => {
  const userInfo = await dbFetch({ user: req.params.userId });

  res.json(userInfo);
});

Router

Router(
  [[ options, ] methods ]
)

options is the options object you would pass to the creation of the router instance
See addAsync for the default methods.

If you want to use a router, import the async-ready version.

const express = require("express");
const { Router } = require("@phoenix35/express-async-methods");

const app = express(); // This app isn't async friendly.
const router = Router(); // But this router is.

router.getAsync("/i-am-error", async (req, res) => {
  await new Promise(resolve => {
    setTimeout(resolve, 100);
  });

  throw new Error("You summoned an error, you devil!");
});

app.use(router);

wrap

If you want granular control, you can wrap individual callback functions.
(NOT for app.param, see below).

const express = require("express");
const { wrap } = require("@phoenix35/express-async-methods");

const app = express();

app.put("/users/:userId", wrap(async (req, res) => {
  await dbUpdate({ user: req.params.userId, newInfo: req.body });

  res.sendStatus(204);
}));

// Regular methods can still be used without wrapping
app.get("/users/:userId", (req, res, next) => {
  dbFetch({ user: req.params.userId }, (err, userInfo) => {
    if (err)
      return next(err);

    res.json(userInfo);
  })
});

wrapParam

Because of the specific signature of app.param, use wrapParam instead.

const express = require("express");
const { wrap, wrapParam } = require("@phoenix35/express-async-methods");

const app = express();

app.param("userId", wrapParam(async (req, res, next, id) => {
  const userInfo = await dbFetch({ user: id });

  if (userInfo == null) {
    throw new TypeError("Failed to load user");
    // next will be called automatically
  }

  req.user = userInfo;
  // next will be called automatically
}));

app.put("/users/:userId", wrap(async (req, res) => {
  await dbUpdate({ user: req.user.id, newInfo: req.body });

  res.sendStatus(204);
}));

Note that app.paramAsync and Router.paramAsync are properly created and handled by default.