You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
I had some trouble with async function calls submitted to setTimeout/setImmediate/setInterval when using faked timers, and it seems that I am not the only one. The problem is that methods like tick and even tickAsync do sometimes return even before the scheduled callbacks have finished.
So it is not possible to have a reproducible state after e.g. tickAsync has returned.
Describe the solution you'd like
I have noticed that there are some plans to mock or stub promises completely, but for now I propose to implement a short workaround that may cover most of the use cases I can imagine:
It should be quite easy for users to make all of their callbacks from the production code returning a promise that is resolved or rejected exactly when the purpose of the callback has been done. As it is a best practice to not have unhandled promises, this may already been the case in clean implementations, even if the original APIs for setTimeout and friends do not expect promises as return types.
So assuming that, you may implement a queue of promises, that is filled with the promises of all callbacks (or their normal return values wrapped as a promise).
constpromiseQueue=newSet()// global or one instance per InstalledClockconstwrappedCallback=(...args: any[])=>{constpromise=Promise.resolve(callback(...args))promiseQueue.add(promise)promise.finally(()=>promiseQueue.delete(promise))}// call internal setTimeout/setImmediate/setInterval with the wrapped callback
The methods tickAsync, runToLastAsync, runAllAsync and nextAsync would than wait for all promises of that queue when called and clear the queue afterwards.
Depending on the used tick-Function (e.g. runAllAsync) you may need to check'n'wait for the promise queue multiple times.
Things to consider
A promise from a user's callback may depend on the execution of other callbacks submitted by e.g. setImmediate. So while waiting for such promises to resolve/reject,
the execution of callbacks from setImmediate, setTimeout(0), etc. should not be blocked.
If the user's callback returns a promise that depends on future executions like setTimeout(100) and the user awaits the result of e.g. tickAsync at the same time, waiting infinite long should be the expected behaviour.
Benefits
Using this workaround all the async tick functions won't return to early anymore,
unless there is a bug in the users promise chain, which is something they probably want to fix anyway.
The text was updated successfully, but these errors were encountered:
Is your feature request related to a problem? Please describe.
I had some trouble with async function calls submitted to setTimeout/setImmediate/setInterval when using faked timers, and it seems that I am not the only one. The problem is that methods like tick and even tickAsync do sometimes return even before the scheduled callbacks have finished.
So it is not possible to have a reproducible state after e.g. tickAsync has returned.
Describe the solution you'd like
I have noticed that there are some plans to mock or stub promises completely, but for now I propose to implement a short workaround that may cover most of the use cases I can imagine:
It should be quite easy for users to make all of their callbacks from the production code returning a promise that is resolved or rejected exactly when the purpose of the callback has been done. As it is a best practice to not have unhandled promises, this may already been the case in clean implementations, even if the original APIs for setTimeout and friends do not expect promises as return types.
So assuming that, you may implement a queue of promises, that is filled with the promises of all callbacks (or their normal return values wrapped as a promise).
The methods
tickAsync
,runToLastAsync
,runAllAsync
andnextAsync
would than wait for all promises of that queue when called and clear the queue afterwards.Depending on the used tick-Function (e.g. runAllAsync) you may need to check'n'wait for the promise queue multiple times.
Things to consider
A promise from a user's callback may depend on the execution of other callbacks submitted by e.g. setImmediate. So while waiting for such promises to resolve/reject,
the execution of callbacks from setImmediate, setTimeout(0), etc. should not be blocked.
If the user's callback returns a promise that depends on future executions like setTimeout(100) and the user awaits the result of e.g. tickAsync at the same time, waiting infinite long should be the expected behaviour.
Benefits
Using this workaround all the async tick functions won't return to early anymore,
unless there is a bug in the users promise chain, which is something they probably want to fix anyway.
The text was updated successfully, but these errors were encountered: