-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import asyncify from '../asyncify'; | ||
|
||
var supportsSymbol = typeof Symbol !== 'undefined'; | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
export default function wrapAsync(asyncFn) { | ||
if (!supportsSymbol) return asyncFn; | ||
|
||
var isAsync = asyncFn[Symbol.toStringTag] === 'AsyncFunction'; | ||
|
||
return isAsync ? asyncify(asyncFn) : asyncFn; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
describe('async function support', function () { | ||
this.timeout(100); | ||
|
||
var supportsAsync; | ||
var supportsSymbol = typeof Symbol !== 'undefined'; | ||
try { | ||
/* eslint no-eval:0 */ | ||
var fn = eval('(async function() {})') | ||
supportsAsync = supportsSymbol && | ||
fn[Symbol.toStringTag] === 'AsyncFunction'; | ||
} catch (e) { | ||
supportsAsync = false; | ||
} | ||
|
||
if (supportsAsync) { | ||
require('./es2017/asyncFunctions.js')(); | ||
} else { | ||
it('should not test async functions in this environment'); | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
var async = require('../../lib'); | ||
const expect = require('chai').expect; | ||
const assert = require('assert'); | ||
|
||
|
||
module.exports = function () { | ||
async function asyncIdentity(val) { | ||
var res = await Promise.resolve(val); | ||
return res; | ||
} | ||
|
||
const input = [1, 2, 3]; | ||
|
||
it('should asyncify async functions', (done) => { | ||
async.asyncify(asyncIdentity)(42, (err, val) => { | ||
assert(val === 42); | ||
done(err); | ||
}) | ||
}); | ||
|
||
it('should handle async functions in each', (done) => { | ||
async.each(input, asyncIdentity, done); | ||
}); | ||
|
||
it('should handle async functions in eachLimit', (done) => { | ||
async.eachLimit(input, 2, asyncIdentity, done); | ||
}); | ||
|
||
it('should handle async functions in eachSeries', (done) => { | ||
async.eachSeries(input, asyncIdentity, done); | ||
}); | ||
|
||
it('should handle async functions in eachOf', (done) => { | ||
async.eachOf(input, asyncIdentity, done); | ||
}); | ||
|
||
it('should handle async functions in eachOfLimit', (done) => { | ||
async.eachOfLimit(input, 2, asyncIdentity, done); | ||
}); | ||
|
||
it('should handle async functions in eachOfSeries', (done) => { | ||
async.eachOfSeries(input, asyncIdentity, done); | ||
}); | ||
|
||
it('should handle async functions in map', (done) => { | ||
async.map(input, asyncIdentity, (err, result) => { | ||
expect(result).to.eql(input); | ||
done(err); | ||
}); | ||
}); | ||
|
||
it('should handle async functions in mapLimit', (done) => { | ||
async.mapLimit(input, 2, asyncIdentity, (err, result) => { | ||
expect(result).to.eql(input); | ||
done(err); | ||
}); | ||
}); | ||
|
||
it('should handle async functions in mapSeries', (done) => { | ||
async.mapSeries(input, asyncIdentity, (err, result) => { | ||
expect(result).to.eql(input); | ||
done(err); | ||
}); | ||
}); | ||
|
||
it('should handle async functions in filter', (done) => { | ||
async.filter(input, asyncIdentity, (err, result) => { | ||
expect(result).to.eql(input); | ||
done(err); | ||
}); | ||
}); | ||
|
||
it('should handle async functions in filterLimit', (done) => { | ||
async.filterLimit(input, 2, asyncIdentity, (err, result) => { | ||
expect(result).to.eql(input); | ||
done(err); | ||
}); | ||
}); | ||
|
||
it('should handle async functions in filterSeries', (done) => { | ||
async.filterSeries(input, asyncIdentity, (err, result) => { | ||
expect(result).to.eql(input); | ||
done(err); | ||
}); | ||
}); | ||
} |
5 comments
on commit 9fc2995
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@megawac @hargasinski I'd love to get your 👀 on this before I continue further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wrapAsync
implementation looks good to me, especially with the refactor in ac0bdd0.
One question though, is there a reason for only wrapping certain iteratee
s in wrapAsync
? Wrapping the iteratee
in internal/eachOfLimit
would give most methods support for async
functions. From #1386, I know async/await
does not make sense in flow controls functions, but I don't see a reason not to support it unless the additional performance of an extra wrapper is a concern?
By the way, is there anything I could help with?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just the first pass with a handful of functions -- I wanted to validate the strategy before applying it to every method.
Wrapping the iteratee in internal/eachOfLimit
does catch a lot of things, but we have to wrap async
functions before they are wrapped with something like withoutIndex
, so it means it will have to be handled in a lot of places.
I think it's worth adding support to control flow functions -- will come in handy if you need to mix and match async
functions and callback functions in the same parallel
call, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really cool! Are there going to be some cases we have to worry about where the async callback has a different form than (err, result)
arguments? For example, would waterfall
/series
be supported?
Anyway, looks like great progress 🥇
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since promises only support resolving to a single value, things like waterfall
would get weird/tricky. You'd have to use arrays like:
async.waterfall([
async function () {
let a = await foo();
return [a, b, c];
}
async function([a, b, c]) {
let d = await bar(a, b, c);
return [a, d];
},
async function ([a, d]) {
// etc...
}
], done)
So the
asyncify
part of this won't be necessary any more? Very cool!