New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wip] POC for await-able Async functions #1526
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,14 @@ | ||
import noop from 'lodash/noop'; | ||
import once from './once'; | ||
|
||
import iterator from './iterator'; | ||
import onlyOnce from './onlyOnce'; | ||
|
||
import breakLoop from './breakLoop'; | ||
import promiseCallback from './promiseCallback'; | ||
|
||
export default function _eachOfLimit(limit) { | ||
return function (obj, iteratee, callback) { | ||
callback = once(callback || noop); | ||
callback = once(callback || promiseCallback()); | ||
if (limit <= 0 || !obj) { | ||
return callback(null); | ||
} | ||
|
@@ -50,5 +50,6 @@ export default function _eachOfLimit(limit) { | |
} | ||
|
||
replenish(); | ||
return callback.promise; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we'll want to track whether the callback is a user defined callback or an internal promise callback and only return |
||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
export default function once(fn) { | ||
return function () { | ||
function wrapped () { | ||
if (fn === null) return; | ||
var callFn = fn; | ||
fn = null; | ||
callFn.apply(this, arguments); | ||
}; | ||
wrapped.promise = fn.promise; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the wrapped function not return a promise instead to allow |
||
return wrapped; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import noop from 'lodash/noop'; | ||
|
||
var supportsPromise = typeof Promise === 'function'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A pretty crude way to detect promise support. This would be a 3.0 feature. I thinking of dropping support for non-ES2015 environments, in which case we could always return a Promise. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 for dropping pre-ES2015 support in v3. |
||
|
||
export default supportsPromise ? promiseCallback : noopCallback; | ||
|
||
function noopCallback() { | ||
return noop; | ||
} | ||
|
||
function promiseCallback() { | ||
var resolve, reject; | ||
function callback(err, value) { | ||
if (err) return reject(err); | ||
resolve(value); | ||
} | ||
|
||
callback.promise = new Promise(function (res, rej) { | ||
resolve = res; | ||
reject = rej; | ||
}) | ||
|
||
return callback; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ var async = require('../../lib'); | |
const expect = require('chai').expect; | ||
const assert = require('assert'); | ||
|
||
const promiseProto = Object.getPrototypeOf(new Promise(()=>{})); | ||
|
||
module.exports = function () { | ||
async function asyncIdentity(val) { | ||
|
@@ -32,8 +33,16 @@ module.exports = function () { | |
* Collections | ||
*/ | ||
|
||
it('should handle async functions in each', (done) => { | ||
async.each(input, asyncIdentity, done); | ||
it('should handle async functions in each', async () => { | ||
var promise = async.each(input, asyncIdentity); | ||
assert(typeof promise.then === 'function'); | ||
assert(Object.getPrototypeOf(promise) === promiseProto); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not simpler? assert(promise instanceof Promise); |
||
await promise; | ||
}); | ||
|
||
it('should handle async functions in each (empty array)', async () => { | ||
var promise = async.each([], asyncIdentity); | ||
await promise; | ||
}); | ||
|
||
it('should handle async functions in eachLimit', (done) => { | ||
|
@@ -56,11 +65,9 @@ module.exports = function () { | |
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 map', async () => { | ||
var result = await async.map(input, asyncIdentity); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 😍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is sweet! It would be cool to also test async with generators, perhaps having a generator function that initializes some data for some of the test cases |
||
expect(result).to.eql(input); | ||
}); | ||
|
||
it('should handle async functions in mapLimit', (done) => { | ||
|
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.
Deliberately never returning anything from an Async function has given us the headroom to do this!