Table of contents:
Introduction
An overview:
-
promisify
-
Callback functions
-
Use async [function definition] and await [function call].
-
Find and us a synchronous version of the asynchronous function for which you are having to use the callback API or async/await.
-
Redesign and refactor your code so that, for example, your use of async/await is at a shallower level in the function call chain.
Promisify
See my other article on promisity
--
Promisify.
Callback functions
A common reason for trying to avoid the use of callbacks is sometimes referred to as "callback hell". It's where one callback function is defined inside the definition of another callback function which in turn is defined in the definition of yet another surrounding callback function and so on.
In some cases you can alleviate that problem by defining a callback
function "out-of-line". That might mean defining a function at top
level (with the function
keyword) and then using in the call to
your asynchronous function.
async
and await
Notes on await
and async
:
-
If you want to make a function call to an asynchronous function into a call that blocks, use
await
. -
An
async
function returns a promise. Useawait
to wait for and resolve that promise, that is, to get the resolved value of that promise. -
You can use
await
only inside a function defined withasync
or at top level. -
Define an asynchronous function (that is, a function that returns a promise) by using the
async
keyword. Examples:async function f1(x) { return x * 3; } const f2 = async function(y) { return y * 4; } const f3 = (async (z) => { return z * 5; });
-
In order to call an asynchronous function and obtain its value (that is, the value of its resolved promise), use
await
. Examples:const result1 = await f1(3); console.log('result1:', result1); const result2 = await f2(4); console.log('result2:', result2); const result3 = await f3(4); console.log('result3:', result3);
-
A promise is "then-able". So, if you'd rather use a callback, you could do this:
f1(6).then((w) => { console.log('w:', w); })
Use a synchronous function
If what you really want is a function that blocks, that is a synchronous function instead of an asynchronous one, you might be able to find one. You can look in the usual places, for example:
-
Nodejs API docs -- https://nodejs.org/docs/latest/api/
-
NPM -- https://www.npmjs.com/ -- For example, I found these:
-
sync-fetch
-- A synchronous version of thefetch
function -- https://www.npmjs.com/package/sync-fetch. -
sync
-- A library that allows you to call any asynchronous function in synchronous way -- https://www.npmjs.com/package/sync
-
Redesign and refactor
When adapting to the above, you might want to redesign or refactor
your code, for example, either in order to avoid "callback hell"
(callbacks nested inside callbacks nested inside ...) or in order to
reduce the need for a long chain of nested async
functions (an
async function that awaits on an async function that awaits ...).
When doing so, keep in mind:
-
With respect to callbacks, code in the body of the callback will usually execute after any mainline code. So, the mainline code must not depend on the callback code. So in this example:
someAsyncFunc(arg1, ((x) => { // callback code })); // mainline code
The mainline code will typically run before the callback code.
And, you may want to define some callback functions "out of line" and at top level.
- With respect to the use of
async
andawait
, you may want to raise the use of those function to as high a level in you code as possible.