JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 267
  • Score
    100M100P100Q82663F
  • License MIT

A route wrapper allowing use of async / await syntax in Express route controllers

Package Exports

  • route-async

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 (route-async) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

route-async

A route wrapper allowing use of async / await syntax in Express route controllers

Greenkeeper badge

Branch Status Coverage Comments
develop CircleCI codecov Work in progress
master CircleCI codecov Latest release

To Use

npm install route-async

Wrap an async route

Assuming you have some helper function called someAsync, you might have a route looking a bit like this:

const asyncRoute = require('route-async')
const someAsync = require('./helpers/someAsync')

const myRoute = async (req, res) => {
  const result = await someAsync(req.body)
  res.json(result)
}

module.exports = asyncRoute(myRoute)

The asyncRoute wrapper simply takes your route and wraps it, such that the async promise is either resolved internally, or if rejected a next function is called. The default next is just console.error but you can of course supply your own.

Testing async routes

The following example leverages mocha, sinon, and proxyquire to unit test the above route.

const { expect } = require('chai')
const sinon = require('sinon')
const proxyquire = require('proxyquire')

describe('src/routes/myRoute', () => {
  const mockSomeAsync = sinon.stub()

  const myRoute = proxyquire('../../src/routes/myRoute', {
    './helpers/someAsync': mockSomeAsync
  }

  const req = { body: 'some body' }
  const res = { json: sinon.stub() }
  const next = sinon.spy()

  const resetStubs = () => {
    res.json.resetHistory()
    next.resetHistory()
  }

  context('no errors', () => {
    const result = 'some result'

    before(async () => {
      mockSomeAsync.resolves(result)
      await myRoute(req, res, next)
    })

    after(resetStubs)

    it('called someAsync with the right data', () => {
      expect(mockSomeAsync).to.have.been.calledWith(req.body)
    })

    it('called res.json with the right data', () => {
      expect(res.json).to.have.been.calledWith(result)
    })

    it("didn't call next", () => {
      expect(next).not.to.have.been.called
    })
  })

  context('has errors', () => {
    const error = 'some error'

    before(async () => {
      mockSomeAsync.rejects(error)
      await myRoute(req, res, next)
    })

    after(resetStubs)

    it('called someAsync with the right data', () => {
      expect(mockSomeAsync).to.have.been.calledWith(req.body)
    })

    it("didn't call res.json", () => {
      expect(res.json).not.to.have.been.called
    })

    it('called next with the error', () => {
      expect(next).to.have.been.calledWith(error)
    })
  })
})

Development

Prerequisites

  • NodeJS, version 10+ or better (I use nvm to manage Node versions — brew install nvm.)

Initialisation

npm install

Test it

  • npm test — runs the unit tests (quick and does not need rabbit mq running)
  • npm run test:coverage — runs the tests with code coverage output.

Lint it

npm run lint

Contributing

Please see the contributing notes.