-
Notifications
You must be signed in to change notification settings - Fork 33.5k
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
Async & Performance: optimize gen-runner in chapter 4 #1210
Comments
Code also shown in chapter 4 of "ES6 & Beyond" |
When I wrote that suggestion the deferring of a tick was intentional for clarity of code - but I don't have strong feelings about it. |
The reason I don't like the extra tick is because an equivalent async function doesn't wait a tick to start, it runs its first part immediately. |
@getify you're right :) I didn't know that would be the case when I first wrote that pump code. Another part of the fact it's wrapped in a |
Ahh, you're absolutely right, totally forgot that was one of the motivations. That should have been commented. ;-) OK, so we need this, huh?: return Promise.resolve(
(function handleNext(value){
try {
var next = it.next(value);
// ..
}
catch (err) {
return Promise.reject(err);
}
})()
); |
Pretty much, yeah, although then you can probably add a |
the other (minor) downside is that this new |
FYI: I've previously adapted this gen-runner to use in another of my projects, CAF. So just tweaked it based on our discussions here: https://github.com/getify/CAF/blob/94c60e2cdba714680f770ca04bd3fe2e5201b830/src/caf.src.js#L58-L98 Thoughts? In particular, I'm curious/pondering if it's better (or different/broken) to move that outer |
(edit): I thought moving the Thoughts? |
CAF looks really interesting, it's a shame we don't have proper cancel token support from the platform. I see you I would probably write it with an function _runner(gen, ...args) {
const it = gen.apply(this, args);
async function result() {
let done = false, value = undefined;
while(!done) {
try {
({done, value}) = it.next(await value);
} catch (e) {
it.throw(e);
}
}
return value;
}
return {it, result() }
} Although I'm not sure of its performance characteristics. What about the perhaps simpler: function _runner(gen, ...args) {
const it = gen.apply(this, args);
function result(oldValue) {
let {done, value} = it.next(oldValue);
return Promise.resolve(value).then(result, it.throw.bind(it));
}
return {it, (async () => result())() } // the `async` lambda is to handle `throw`s
} |
My main reason for not making it an |
We do have the web platform's standard of |
@getify What about that? function run(gen, ...args) {
let it = gen(...args);
let next;
try {
next = it.next();
return handleValue(next);
} catch (err) {
return Promise.reject(err);
}
function handleErr(err) {
return Promise.resolve(it.throw(err)).then(handleValue);
}
function handleValue(next) {
if (!next.done) {
return Promise.resolve(next.value).then(nextStep, handleErr);
} else {
return Promise.resolve(next.value);
}
}
function nextStep(value) {
next = it.next(value);
return handleValue(next);
}
} |
In the promise-aware gen runner, to prevent the unnecessary extra tick at the beginning, change:
...to:
The text was updated successfully, but these errors were encountered: