| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
There was a problem hiding this comment.
Assigning passCallback and abortCallback seems unnecessary here.
| if (abortCallback) { | |
| abortCallback(new AbortError()); | |
| passCallback = undefined; | |
| abortCallback = undefined; | |
| } | |
| abortCallback?.(new AbortError()); |
Sorry, something went wrong.
There was a problem hiding this comment.
the undefinds are there because otherwise we sometimes get an error during the tests because of multiple resolves (as we could resolve the promise and then someone aborts the iterator).
Sorry, something went wrong.
There was a problem hiding this comment.
Could you move those to after the await new Promise to avoid the repetition? No strong feeling though, if you prefer as it is now, feel free to disregard, I'd personally find it easier to follow if it were down there.
Sorry, something went wrong.
There was a problem hiding this comment.
Actually, that's where I originally put it. However, it's incorrect because you could still resolve and reject before the await yields, and get multiple resolves.
Sorry, something went wrong.
There was a problem hiding this comment.
Shouldn't we import this from timers?
Sorry, something went wrong.
There was a problem hiding this comment.
I could, I just saw that clearTimeout also wasn't imported (I actually copied the exact same comment from that one)
Sorry, something went wrong.
There was a problem hiding this comment.
Again, assigning the variables to undefined seems unnecessary
| if (passCallback) { | |
| passCallback(); | |
| passCallback = undefined; | |
| abortCallback = undefined; | |
| } | |
| passCallback?.(); |
Sorry, something went wrong.
There was a problem hiding this comment.
the undefinds are there because otherwise we sometimes get an error during the tests because of multiple resolves (as we could resolve the promise and then someone aborts the iterator)
Sorry, something went wrong.
There was a problem hiding this comment.
Can we get rid of the if statement by moving the for loop above the await new Promise?
Sorry, something went wrong.
There was a problem hiding this comment.
I think that we would get an issue like the following:
suppose that the promise was fulfilled, and before we got back to it the interval was somehow aborted. we'll go back to the while condition and get out of the while loop, instead of yielding the value.
Sorry, something went wrong.
There was a problem hiding this comment.
Good job, left a few comments!
Sorry, something went wrong.
|
Is it possible to break out of the loop to stop the interval (there doesn't seem to be a test for that case)? |
Sorry, something went wrong.
A test for that case is a good idea, I think indeed a finally clause clearing the interval is missing here. |
Sorry, something went wrong.
|
@Linkgoron I think what Michael meant is that you can break inside a for await loop and that calls .return on the async generator. |
Sorry, something went wrong.
There was a problem hiding this comment.
| }); | |
| }); | |
| passCallback = undefined; | |
| abortCallback = undefined; |
Sorry, something went wrong.
There was a problem hiding this comment.
Could you move those to after the await new Promise to avoid the repetition? No strong feeling though, if you prefer as it is now, feel free to disregard, I'd personally find it easier to follow if it were down there.
Sorry, something went wrong.
Oh. I didn't know that! Anyway, I'll update the PR soon. |
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks, good job. I think this is good enough to land (the module is experimental) and iron out small nits later :]
Sorry, something went wrong.
|
Just a thought: could we easily make the iterated values resolve to the number of iterations? |
Sorry, something went wrong.
|
@targos I would prefer that as well - but James raised the point in the original PR that setTimeout from timers/promises already does this with the value parameter. |
Sorry, something went wrong.
Sorry, something went wrong.
Sorry, something went wrong.
Sorry, something went wrong.
Sorry, something went wrong.
Sorry, something went wrong.
Added setInterval async generator to timers\promises. Utilises async generators to provide an iterator compatible with `for await`. Co-Authored-By: Fabian Cook <hello@fabiancook.dev> fix message PR-URL: #37153 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
| { | ||
| // Check that if we abort when we have some callbacks left, | ||
| // we actually call them. | ||
| const controller = new AbortController(); | ||
| const { signal } = controller; | ||
| const delay = 10; | ||
| let totalIterations = 0; | ||
| const timeoutLoop = runInterval(async (iterationNumber) => { | ||
| if (iterationNumber === 2) { | ||
| await setTimeout(delay * 2); | ||
| controller.abort(); | ||
| } | ||
| if (iterationNumber > totalIterations) { | ||
| totalIterations = iterationNumber; | ||
| } | ||
| }, delay, signal); | ||
|
|
||
| timeoutLoop.catch(common.mustCall(() => { | ||
| assert.ok(totalIterations >= 3, `iterations was ${totalIterations} < 3`); | ||
| })); | ||
| } | ||
| } |
There was a problem hiding this comment.
Unfortunately, this test is unreliable and is failing in CI on Raspberry Pi devices. I also can make it fail trivially on my macOS laptop by running tools/test.py -j96 --repeat=192 test/parallel/test-timers-promisified.js. I haven't looked closely (yet) but in my experience, having a magic number delay variable like this in a timers test indicates an assumption that the host isn't so slow that (say) a 10ms second timer won't fire 50ms later. This assumption is, of course, incorrect if the machine has low CPU/memory (like a Raspberry Pi device) or if there are a lot of other things competing for the machine's resources (-j96 --repeat=192).
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry for causing an issue - I'll take a look and fix it
Sorry, something went wrong.
There was a problem hiding this comment.
When implementing this, I was under the assumption that if we I have an interval and a timeout where the interval starts before a timeout and is supposed to execute before the timeout executes, the interval's callback would always execute before the timeout's callback. Either this assumption was wrong, or something in my setInterval implementation is incorrect. (i.e. I thought that the setTimeout would always run after the internal setInterval)
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry, something went wrong.
Added setInterval async generator to timers\promises. Utilises async generators to provide an iterator compatible with `for await`. Co-Authored-By: Fabian Cook <hello@fabiancook.dev> fix message PR-URL: #37153 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Notable Changes: * crypto: * add keyObject.export() 'jwk' format option (Filip Skokan) #37081 * deps: * upgrade to libuv 1.41.0 (Colin Ihrig) #37360 * doc: * add dmabupt to collaborators (Xu Meng) #37377 * refactor fs docs structure (James M Snell) #37170 * fs: * add fsPromises.watch() (James M Snell) #37179 * use a default callback for fs.close() (James M Snell) #37174 * add AbortSignal support to watch (Benjamin Gruenbaum) #37190 * perf_hooks: * introduce createHistogram (James M Snell) #37155 * stream: * improve Readable.from error handling (Benjamin Gruenbaum) #37158 * timers: * introduce setInterval async iterator (linkgoron) #37153 * tls: * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
Notable Changes: * crypto: * add keyObject.export() 'jwk' format option (Filip Skokan) #37081 * deps: * upgrade to libuv 1.41.0 (Colin Ihrig) #37360 * doc: * add dmabupt to collaborators (Xu Meng) #37377 * refactor fs docs structure (James M Snell) #37170 * fs: * add fsPromises.watch() (James M Snell) #37179 * use a default callback for fs.close() (James M Snell) #37174 * add AbortSignal support to watch (Benjamin Gruenbaum) #37190 * perf_hooks: * introduce createHistogram (James M Snell) #37155 * stream: * improve Readable.from error handling (Benjamin Gruenbaum) #37158 * timers: * introduce setInterval async iterator (linkgoron) #37153 * tls: * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
PR-URL: #37406 Notable Changes: * crypto: * add keyObject.export() jwk format option (Filip Skokan) #37081 * deps: * upgrade to libuv 1.41.0 (Colin Ihrig) #37360 * doc: * add dmabupt to collaborators (Xu Meng) #37377 * refactor fs docs structure (James M Snell) #37170 * fs: * add fsPromises.watch() (James M Snell) #37179 * use a default callback for fs.close() (James M Snell) #37174 * add AbortSignal support to watch (Benjamin Gruenbaum) #37190 * perf_hooks: * introduce createHistogram (James M Snell) #37155 * stream: * improve Readable.from error handling (Benjamin Gruenbaum) #37158 * timers: * introduce setInterval async iterator (linkgoron) #37153 * tls: * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
PR-URL: #37406 Notable Changes: * crypto: * add keyObject.export() jwk format option (Filip Skokan) #37081 * deps: * upgrade to libuv 1.41.0 (Colin Ihrig) #37360 * doc: * add dmabupt to collaborators (Xu Meng) #37377 * refactor fs docs structure (James M Snell) #37170 * fs: * add fsPromises.watch() (James M Snell) #37179 * use a default callback for fs.close() (James M Snell) #37174 * add AbortSignal support to watch (Benjamin Gruenbaum) #37190 * perf_hooks: * introduce createHistogram (James M Snell) #37155 * stream: * improve Readable.from error handling (Benjamin Gruenbaum) #37158 * timers: * introduce setInterval async iterator (linkgoron) #37153 * tls: * add ability to get cert/peer cert as X509Certificate object (James M Snell) #37070
|
I'm marking this dont-land-on-v14.x because timers/promises is not available on v14.x. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Added setInterval async generator to timers\promises. Utilises async generators to provide an iterator compatible with
for await. This is a continuation of initial work by Fabian Cook #35841 (who is also marked as co-author in this PR). The async-generator throws an AbortError when aborted.
Note that there are some decisions I've made regarding (so-called) backpressure. If multiple iterations were completed before a value is yielded, the next iteration won't wait delay long, but yield the next value in the next tick. In addition, if there was backpressure before the controller was aborted, the generator will emit all of the passed intervals, and only then finish the iteration. I'd be happy to change this behavior if this is not what's expected (i.e. change the generator to stop producing immediately).
See the previous PR for more information and discussions.
Example:
const { setInterval } = require('timers/promises'); const ac = new AbortController(); const { signal } = ac; const interval = 10; setTimeout(() => ac.abort(), 500); let i=0; for await (const value of setInterval(interval, undefined, { ref: false, signal })) { console.log(Date.now(), i); if(i++>=5) { break; } }