How to diagnose and troubleshoot JavaScript async/await issues

January 25, 2020
an image

By Mike on 19th Sep 2017

Following why you should flatten your JavaScript and our guide to flattening your JavaScript, this is a quick guide to troubleshooting async/await issues. It's only four items because they're what we typically encountered when refactoring the CertSimple code to use await.

Symptom: you log a value and it's a Promise, rather than the object you expect.

> console.log(person.orders)
Promise {
    undefined,
    domain:
     Domain {
         domain: null,
         _events: { error: [Function: debugDomainError] },
         _eventsCount: 1,
         _maxListeners: undefined,
         members: [] } }

You forgot await when you set person.orders.

Symptom: something that isn't a syntax error is reported as a syntax error.

So you've got eslint (and eslint-must-use-await of course) and a random variable suddenly becomes a syntax error?

an image

Does the variable name have an await immediately beforehand? ESLint is actually complaining about a missing async at the top of the function.

Symptom: promisify() doesn't work on a method

Sometimes node 8's util.promisify() seemingly just doesn't work. Call a method regularly, it's fine, but promisify it and it starts producing strange errors.

For example, here's Bing API being promisified:

var searchBing = util.promisify(Bing.web);

After we use it, we'll get:

(node:1752) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: this.searchVertical is not a function

Huh? searchBing now doesn't work but we haven't done anything asides from promisify it! The key is the this in the error: JavaScript's promiscuous this also affects promisifying. The fix is easy: just bind then promisify:

var searchBing = util.promisify(Bing.web.bind(Bing));

Thanks for this person on Stack Overflow for helping me out there.

Symptom: something just stops.

Calling a piece of code and it just... stops?

An async/await refactor often goes like this:

  • Start by wrapping your libraries in util.promisify().
  • Refactor that code to remove callbacks and return Promises.

Which is reasonable. A common error is doing that and then forgetting to remove the original promisify() - accidentally promisifying something that now already returns a promise.

The symptoms for this are simple: your code just stops at the double-promised function. The solution is also pretty simple: remove the no-longer-needed util.promisify().

That's all

We hope this has been useful. We expect there'll probably be some discussion on Hacker News too.