`async` Function Support
See original GitHub issueOne of the elephants in the room is the new async
/await
support that has come to Node and Chrome, and will soon hit every other major browser. I’ve been thinking about what Async can do in the async
/await
world.
Currently, we can adapt async
functions by wrapping them with asyncify
. Since an async
function is essentially just a function that returns a Promise, that old adapter can easily convert it to a callback-style function. However, it leads to the somewhat absurd looking:
async.mapLimit(arr, 10, async.asyncify(async (val) => {
let foo = await doSomething(val);
//...
return bar;
}), done);
However, one of the features in the spec for async
functions is that:
Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
This gives a way to easily detect (native) async
functions. We could use this technique to automatically asyncify
them. The example above becomes:
async.mapLimit(arr, 10, async (val) => {
let foo = await doSomething(val);
//...
return bar;
}, done);
…which seems to flow much more naturally. I also think we should continue to use callbacks. If a user wanted to await
the result, they would have to promisify
the function, or pify
Async as a whole:
let result = await pify(async.mapLimit)(arr, 10, async (val) => {
let foo = await doSomething(val);
//...
return bar;
});
The above method for detecting async
functions only works with native functions. I don’t think there is a way to detect Babel transpiled functions. We certainly can’t detect normal functions that simply return Promises, because we’d have to retroactively not pass a callback. There would he a huge caveat that this would only work without a transpiler in very modern environments, otherwise you still have to manually wrap with asyncify
.
Also, admittedly, many Async methods don’t make sense with async
/await
. Most of the control flow methods (save for things like auto
and queue
) are more easily replicated with native control flow constructs. map
and parallel
can be replaced with Promise.map
and Promise.all
. However, the limiting collection functions would be very useful, as well as auto
and a few others. (Also, autoInject
with async
functions is a async control flow dream!)
Issue Analytics
- State:
- Created 7 years ago
- Reactions:4
- Comments:10 (1 by maintainers)
Top GitHub Comments
Thats just the canonical ECMA spec way to do it. I guess in theory, someone could overwrite
asyncFn[Symbol.toStringTag]
.I think you have it a bit backwards. Wherever we accept an callback-accepting iteratee function (
function(args..., callback) {}
), we should check to see if it is anasync
function, and thenasyncify
it.The
await
example is what someone would have do if they wanted toawait
an Async method. I don’t think we should have Async methods start returning promises so that would work – leave it for the user to do.This was a breaking change and broke our deployed code. Please think twice when doing such things without increasing the major version.
PS: thanks for all the great work you’re doing with this library 😄