'Zombie promises' continuing after a mocha.js test timeout - javascript

I'm using a testing setup with Mocha.js and a lot of promises within the tests. The tests depend on setting up stuff in the DOM, and between tests, the DOM is cleared. However, sometimes the tests run slowly and time out. In this case, their promises continue to execute but the DOM is cleared before the next test, so the promise may incorrectly throw errors into the next test. Is there a way to cancel or destroy all outstanding promises in-between tests? We are using when.js promises.

when.js supports a cancel() method. You could call it from a afterEach or after block in mocha. You might need to create an array at the top of each mocha file (or as global) to track your outstanding promises.

Related

Configure Jest to await all pending promises before tearing down

Is it possible to configure jest to await any pending promises before exiting, to avoid log noise caused by pending code being called after the last test is finished, at which point jest will have torn down the environment?
I have an application which starts by initializing some services asynchronously. If calls are made to these services, the pending background work will first be awaited, and then the task executed. If no calls are made however, the services will invisibly be running init code in the background that no-one cares about.
The problem arises when my tests finish too quickly; if this happens before this pending init work is done, strange things happen - my log gets full of noise which I at first couldn't at all understand - calls like JSON.stringify would fail with cannot access JSON of object null, which turned out to be because jest had torn down the environment so that the global object, containing symbols like JSON was now null (_environment.global.JSON).
I can add an afterAll() hook that simply waits for a second or so, but this seems ugly, and also adds the question what kind of delay is needed; this might break randomly if initialization sometimes takes 100 ms and sometimes 1100 ms.
I could of course add code to afterAll() that makes dummy service calls simply to guarantee that any pending initialization is awaited.
But I would rather like a general, configuration based approach to this, if there is one?
So, is there a way to tell jest to await all pending promises, either before tests start or after?
Or is there a way to tell jest to add a grace period at the end, after all tests, without having to resort to a manual afterAll() call (which must be placed in a file which all tests import, to still have it working properly if only running some tests etc)?
This question actually asks the same question, but the answer with 177 upvotes doesn't do what the question asked for - it simply awaits any promises that are already fulfilled but not handled by the micro tasks queue yet. It does not await any promises that are still pending.

Protractor and promises

A lot of the functions exposed by Protractor return promises.
Do I need to structure my Jasmine tests using Protractor using things like async tests (with the done parameter), and .then, or does Protractor provide some magic to do this for me?
WebDriverJS takes care of that with the control-flow. Protractor adds the modification of Jasmine's expect to keep the thens at bay. It's best explained here.
Yes, there is some magic that protractor performs in order to wait for each promise to resolve.
The best description of the process is in the protractor documentation: How It Works.
This means we don't have to structure the tests as async using a done. We can simply assert using expect (in Jasmine) and everything should work.

Resolving promises without a digest cycle

AngularJS promises seem to be tied to a digest cycle, as in, the success/error callbacks are not called until a digest cycle is run. This means that anything that uses promises, such as $http or manually created promises, also need to trigger a digest cycle in order to get the callbacks to run.
Is it possible to use promises in Angular, without the digest cycle being run at all? I realise you can use $applyAsync, which schedules the digest cycle for a bit later, but I'm looking to not run the digest cycle at all, and still have the then callbacks run.
Essentially I'm trying to work out how to squeeze as much performance as possible from an app that would use a fair bit of asynchronous behaviour that would need promises resolved but not necessarily the digest cycle run.
No, it is currently not possible. Whenever a then handler runs it schedules the callback via $evalAsync which schedules a digest if one is not already scheduled.
The exception to this is $timeout that accepts an extra argument to not run a digest. On the other hand - multiple promises that resolve in the same turn run on the same digest.
Your options are:
- Use XMLHttpRequqest directly, seriously - it's not very hard. The biggest downside to this is that it will not respect interceptors and other $http hooks (like the mock backend).
- Decorate $q to not schedule via $evalAsync or add a .thenNoDigest method to the promise prototype that schedules via setTimeout.
- Use a userland promise library instead of $q for $http or over XHR.

Promise.resolve().then vs setImmediate vs nextTick

NodeJS 0.11 as well as io.js and the Node 0.12 branch all ship with native promises.
Native promises have a .then method which always executes on a future event loop cycle.
So far I've been using setImmediate to queue things to the next iteration of the event loop ever since I switched from nextTick:
setImmediate(deferThisToNextTick); // My NodeJS 0.10 code
process.nextTick(deferThisToNextTick); // My NodeJS 0.8 code
Since we now have a new way to do this:
Promise.resolve().then(deferThisToNextTick);
Which should I use? Also - does Promise.resolve.then act like setImmediate or like nextTick with regards to code running before or after the event loop?
Using Promise.resolve().then has no advantages over nextTick. It runs on the same queue, but have slightly higher priority, that is, promise handler can prevent next tick callback from ever running, the opposite is not possible. This behaviour is an implementation detail and should not be relied on.
Promise.resolve().then is obviously slower (a lot, I think), because it creates two promises which will be thrown away.
You can find extensive implementation info here: https://github.com/joyent/node/pull/8325
The most important part: Promise.resolve().then is like nextTick and not like setImmediate. Using it n place of setImmediate can change your code behaviour drastically.
I'm not going to answer the bolded part about technicalities, but only the question
Which should I use?
I don't think there is any reason to use Promise.resolve().then() unless you are interested in the promise for the result of your asynchronously executed function. Of course, if you are, then this would be far superior than dealing with callback hell or making a new Promise from setTimeout or nextTick.
There's also a second technical difference, more import than the timing: promises do swallow exceptions. Which you probably don't want. So, like #vkurchatkin mentioned, don't create promises only to throw them away. Not only because it's slower, but because it makes your code less readable and your app more error-prone.
Promise.resolve would be resolved straight away (syncroniously), while setImmediate explicitly straight after the execution of current event.

Javascript Promises library to make "long-running-code-non-blocking-UI" in browser?

Update
this an update to the question below and should help finding an answer
Taking up the answer from torazaburo who also quoted part of the prominent Javascript Promise/A+ definition I want to update the question here.
The Promise/A+ specification suggest in point 2.2.4 this:
onFulfilled or onRejected must not be called until the execution
context stack contains only platform code. 3.1.
and further explains
Here “platform code” means engine, environment, and promise
implementation code. In practice, this requirement ensures that
onFulfilled and onRejected execute asynchronously, after the event
loop turn in which then is called, and with a fresh stack. This can be
implemented with either a “macro-task” mechanism such as setTimeout or
setImmediate, or with a “micro-task” mechanism such as
MutationObserver or process.nextTick. Since the promise implementation
is considered platform code, it may itself contain a task-scheduling
queue or “trampoline” in which the handlers are called.
The very issue I look forward to find with this question is having as the crucial point that Promise implementation Javascript code is itself considered platform code and allows to not yield to the eventloop inbetween resolving subsequent promise via calling the onFulfilled onRejected functions associated. This is good in Node.js(server) as it avoids unnessary relinguishing back to the event-loop (leaving the execution stack), but also causes the challange in a Browser that since the execution stack is not exited in between resolving a potentially large number of Promises (which themselves can generate new Promises). Not leaving the execution stack and yielding to the event loop is causing in a Browser the undesired (blocking script warning/problem).
The "trampoline" task-scheduling of the Promise implementation which causes this needs however not necessary refrain from handing back the execution to the Javascript event loop from time to time. Such a feature would allow for using Promises for heavier tasks. Such an implementation for Promises for "long-running-code" is searched/asked for in this question.
Clarification: The "excessive lenght" is not the individual length of the onFulfilled function, but the joining together several those functions/callbacks as result of the Promise resolving process (when done in such a "trampoline" way). I am already aware that if one individual onFulfilled funciton is too long, this cannot be helped in any way by using any sort of Promise implementation.
The deal here is that the subsequent resolvement of x promises (within one excecution stack and hence without handing back to the Javascript event loop) can provoke an excessive length duration of Javascript code execution. This, when in a Browser is bad (because of blocking).
The question
In Javascript, Promises allow to deal with asynchronous programming tasks. Great!
There are already some implementations and libraries arround Q, WinJS or when.js to name just a few.
Having looked at then I see that they tackle some of the "special things" in Javascript asynchronous programming challanges.
Normally I perceive them to do this for promise resolution
Go to the internal list of promises
Check if the promise is fullfilled + run all the associated (via then(onFullfilled,onReject)) functions.
(in some cases we are done here)
(in other cases there will be still "pending" promises)
This case (4) is because to have them (the remaining promises) fullfilled would need the current Javascript Code (which is this very code for promise resolution) to stop running and allow JS event loop to happend (i.e asynchronous things like XHR-requests, or User-UI-interaction). To make this (4) work, the promise resolution normaly schedules a recall (i.e. via setTimeout/setImmediate) and continues after the event loop ran and hence maybe some of the "pending" promises have been settled (=rejected/fullfilled).
My worry is that the step 1 and 2 could be runnning for quite a some time, only releasing execution to the event loop in case it seems indicated to settle some of the "pending" promises. While "okay" in some cases (i.e. on the server/Node.js) it is quite problematic in a browers, because even though it was no problem to release execution to the event loop and have the UI not-blocking, this is not done in the implementations of promises I have seen.
My question therefore is:
Do you know a promise implementation (Javascript Promises library) that cares for the aspect:
to make "long-running-code-non-blocking-UI" in browser?
which would mean that the promise resolution would voluntarily release execution back to the event loop so that CSS animations, user input, mouse interaction, does get enough attention and that there will be no "Warning: Unresponsive script" message.
Any compliant promises implementation will not run the then functions synchronously, but rather only at the next tick. Therefore, your worry that "step 1 and 2 could be runnning for quite a some time" is unfounded.
From the Promises/A+ spec:
onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
Here "platform code" means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack.
In other words, your formulation under 2) is incorrect. The promises implementation does not "run the associated functions", it schedules them.
This cannot help you--indeed there is no way to help you--if a handler itself is "long-running" code.
I think the solution could be to parse that long-running JavaScript code for example with https://github.com/NeilFraser/JS-Interpreter.
It will make the code be even slower, but you could specify the priority:
const myInterpreter = new Interpreter(myCode);
function nextStep() {
if (myInterpreter.step()) {
window.setTimeout(nextStep, 100/speed);
}
}
nextStep();

Categories