Sitemap

Avoid Bugs When Using the async Package for Sequential Function Execution

2 min readOct 3, 2020

The functions in the async package that implement sequential function execution, such as waterfall and eachSeries, accept an array of functions. The provided functions execute sequentially in the order of the provided array.

Each function in the array accepts a function as their last argument. This parameter is typically named next. The next function accepts a truthy value indicating whether an error occurred. Passing a falsey value to next causes the next function in the array to be invoked. Passing a truthy value to next terminates to call chain.

Example:

Avoid passing next to any function as the ‘callback’ parameter

A function in the provided array can pass values to the function that executes immediately after it. In other words, function 1 generates values that are passed to function 2. These parameters are listed before the next parameter, which is always last.

Unfortunately, this feature can easily introduce bugs that are difficult to identify when reading the code.

Although it’s tempting because it’s cleaner, do not change the first function in the above example to the following:

(next) => { // function 1
async_function(next);
}

If the external function passes a value to the callback in the form of (falsey, value), which is common, value will be passed to the following function as the first argument. the second parameter will be ‘next.’ Thus, the following function in the provided array must be declared as: (value, next) => { … }. If it is instead declared as (next) => { … }, the error ‘next is not a function’ will be thrown.

To pass a value to the following function in the provided array, you must call next consistently (e.g., next(falsy value, result value)) and modify the function’s signature:

The above code is brittle because async_function could change over time. If async_function calls the callback with fewer than two arguments, e.g., next(false), the next function in the array will be passed a function for the value argument and the next argument will be undefined, and an exception will be thrown. Another error would occur if the function was changed to pass three or more arguments. To be on the safe side, function 1 should call next:

To reiterate, next must be called consistently. What’s wrong with the following code?

Line 4 in (next()) sends the following arguments to function 2:

  • value = a function. The async package always passes a function as the last argument to the following function in the array.
  • next = undefined

Function 2 will therefore throw an exception when it calls next() and “next” is undefined. Line 4 should instead be written as next(undefined). Therefore, value will be undefined and next will contain a function reference.

--

--

Terris Linenbach
Terris Linenbach

Written by Terris Linenbach

Coder since 1980. Always seeking the Best Way. CV: https://terris.com/cv

No responses yet