I've got a Web application that continuously polls for data from the server using Ajax requests. I would like to implement an integration test for it using zombie.js.
What I am trying to do is to wait until the Ajax poll loop receives data from the server. The data should be received after 20 seconds, so I use browser.wait(done, callback) to check if the data is there, and set waitFor to a maximum timeout of one minute.
However, browser.wait() always returns almost immediately, even if my done callback returns false.
In the zombie API documentation, I read the following about browser.wait():
... it can't wait forever, especially not for timers that may fire repeatedly (e.g. checking page state, long polling).
I guess that's the reason for the behavior I see, but I don't really understand what's going on. Why can't I wait for one minute until my poll loop receives data from the server? Why can't browser.wait() wait for timers that may fire repeatedly? What do I need to do to implement my test?
Zombie.js will by default wait untill all the scripts on your page have loaded and executed if they are waiting for document ready.
If I understand you correctly, your script will not execute til after 20 seconds of document ready. In that case Zombie has a function which will let you evaluate javascript in the context of the browser, so you can kick off your ajax code quicker if it is on a timer, and you do not want to wait for it.
Look at browser.evaluate(expr)
Another option would be to simply use a normal JavaScript timeout to wait 20 seconds, and then look at the DOM for the changes you are expecting.
setTimeout(function(){
browser.document.query("#interestingElement")
}, 20*1000);
Related
I read some artirle talk about nodejs work as single thread. It talked nodejs handle second request after finished first request. So i try to test it. I have some code like
this. Then i send three request sequentially:
http://localhost:3000/?wait=1 : start at **14:29:14**.469Z
http://localhost:3000/?wait=1 : .........**14:29:19**.496Z
http://localhost:3000/ : .........**14:29:15**.725Z
I dont understand. I though third request should be started at 14:29:19, right ? or i misunderstood. Please explain for me, thanks everyone!
Javascript (not just node.js but even your web browser regardless if it's Chrome or Safari or IE or Edge) is single threaded. The structure of the javascript interpreter can generally be described by the following pseudocode:
script_to_exec = compile_js_from_files()
do {
event_queue = execute_javascript(script_to_exec)
completed_events = wait_for_events()
for_each (event from completed_events) {
this_event = event_queue.find_one_matching(event)
script_to_exec = this_event.callback
}
} while (there_is_pending_events)
You may notice that there is no threading code at all in the above code. All we are doing in wait_for_events() is to use the async I/O API provided by the OS. Depending on the OS this can be something like the POSIX select() or the Linux and OSX poll() or BSD epoll() or Windows overlapped I/O functions. Node uses the libuv library which will automatically select the best API to use at compile time.
Loop round 1
Ok. So first round of the loop it executes your entire code. This sets up a TCP socket listener when you set up express. Then it gets stuck at wait_for_events()
The first HTTP request causes wait_for_events() to return. This causes Express to go through your list of middlewares and routes to find a route to execute. It finds your route and calls wait() which calls setTimeout() which adds its callback to the list of timers.
Loop round 2
Since there is no more javascript to execute until await returns we go round the loop again and get stuck at wait_for_events() again.
The second HTTP request causes wait_for_events() to return. This causes Express to go through your list of middlewares and routes and repeat what I described previously.
Loop round 3
Since there is no more javascript to execute until await returns we go round the loop again and get stuck at wait_for_events() again.
The third HTTP request causes wait_for_events() to return. This causes Express to go through your list of middlewares and routes and repeat what I described previously.
Loop round 4
Again, we go round the loop again and get stuck at wait_for_events().
The first await wait() timer expires. This causes wait_for_events() to return and javascript figures out that the event is the timer for that wait therefore it continues processing the first HTTP request. This causes Express to send a response.
Loop round 5
We go round the loop again and wait for wait_for_events().
The second await wait() timer expires. This causes wait_for_events() to return and javascript figures out that the event is the timer for that wait therefore it continues processing the second HTTP request. This causes Express to send a response.
Loop round 6
We go round the loop again and wait for wait_for_events().
The third await wait() timer expires. This causes wait_for_events() to return and javascript figures out that the event is the timer for that wait therefore it continues processing the third HTTP request. This causes Express to send a response.
Loop round 7
We go round the loop again and get stuck at wait_for_events() again waiting for more HTTP requests...
Summary
Basically javascript can wait for multiple things in parallel. This evolved out of the fact that it started as a GUI scripting language that had to have the ability to wait for things like mouse click, keyboard input etc. But it can only execute one instruction at a time (unless of course you deliberately use features to execute additional processes/threads such as web workers or worker threads).
If you're wondering why people use node.js for high performance web servers I have written an answer to this related question explaining why node is fast: Node js architecture and performance
Here's some of my other answers going into different levels of details about asynchronous execution:
I know that callback function runs asynchronously, but why?
Is my understanding of asynchronous operations correct?
Is there any other way to implement a "listening" function without an infinite while loop?
node js - what happens to incoming events during callback excution
I know that callback function runs asynchronously, but why?
Can the execution of an expressJS method be delayed for 30 days or more just by using setTimeout ?
Let's say I want to create an endpoint /sendMessage that send a message to my other app after a timeout of 30 days. Will my expressJS method execution will last long time enough to fire this message after this delay ?
If your server runs continuously for 30 days or more, then setTimeout() will work for that. But, it is probably not smart to rely on that fact that your server never, ever has to restart.
There are 3rd party programs/modules designed explicitly for this. If you don't want to use one of them, then what I have done in the past is I write each future firing time into a JSON file and I set a timer for it with setTimeout(). If the timer successfully fires, then I remove that time from the JSON file.
So, at any point in time, the JSON file always contains a list of times in the future that I want timers to fire for. Any timer that fires is immediately removed from the JSON file.
Anytime my server starts up, I read the times from the JSON file and reconfigure the setTimeout() for each one.
This way, even if my server restarts, I won't lose any of the timers.
In case you were wondering, the way nodejs creates timers, it does not cost you anything to have a bunch of future timers configured. Nodejs keeps the timers in a sorted linked list and the event loop just checks the time for the next timer to fire - the one at the front of the sorted list (the rest of the timers are not looked at until they get to the front of the sorted list). This means the only time it costs anything to have lots of future timers is when inserting a new timer into the sorted list and there is no regular cost in the event loop to having lots of pending timers present.
I used to consider async as equavelent as multithreading. Multi tasks will be done parallel. However, in javascript I wrote this and it seems that dosomething will never happen.
setTimeout(1000, dosomething)
while(true){}
Why?
Node.js is a single threaded asynchronous language. As mentioned in another answer
Javascript is single threaded (with the exception of web workers, but that is irrelavent to this example so we will ignore it). What this means is that setTimeout actually does is schedules some code to be executed some time in the future, after at least some amount of time, but only when the browser has stopped whatever else it was doing on the rendering thread at the time, which could be rendering html, or executing javascript.
In your example the execution of the while loop never stops, control is never returned to the top level, so the scheduled setTimeout function is never executed.
Multithreading is one of many ways to implement asynchronous programming. Reacting to events and yielding to a scheduler is one other way, and happens to be the way that javascript in the browser is implemented.
In your example, the event that gave you control and allowed you to call setTimeout must be allowed to complete so that the javascript engine can monitor the timeout and call your doSomething callback when it expires.
I would like to add a one hour timeout to this process so that it will not stay forever in the case of a stream deadlock. The only problem is if I say setTimeout, the process has no opportunity to end ahead of schedule.
Is there a way to put in a forced exit timeout after about an hour, without keeping the process running? Or am I stuck between using process.exit and doing without this timeout?
I don't know when unref was added to Node but this is now one possible solution. Reusing Matt's code:
var timeoutId = setTimeout(callback, 3600000);
timeoutId.unref(); // Now, Node won't wait for this timeout to complete if it needs to exit earlier.
The doc says:
In the case of setTimeout when you unref you create a separate timer that will wakeup the event loop, creating too many of these may adversely effect event loop performance -- use wisely.
Don't go hog wild with it.
If you save the value returned by setTimeout you can always cancel it before it fires with clearTimeout, like this:
var timeoutId = setTimeout(callback, 3600000); // 1 hour
// later, before an hour has passed
clearTimeout(timeoutId);
Possible Solution using a new feature that was implemented as process.watchers(), but I don't know whether it was included in a released version yet. The pull request is still open as of this post.
But generally speaking, you would write a custom setTimeout function that add all timeouts to a counter, and right before the timeouts to the callback, it would remove from the counter.
Then create an ongoing interval, and the interval would check and notice when all the walkers are just timeouts set by your custom function.
When it notices this, it would (clear all of its those timeouts, causing an) exit.
This of course is not great, because
The concept is not proven. (I do not know what kind of data will be returned by process.watchers(), or if it even works yet)
The interval is a polling method. (not nice if you want immediate return at the same time as low CPU usage)
I have a application in which i am sending a SMS to the Server which will return the result as an SMS. So i have put a Message Intercepter with the Event Handler. The Problem is that Once i send the request i have to wait for 30 seconds before i go ahead with the operation. How do i make my application wait till that. if i use the Thread.sleep it is making the whole application sleep and i am not getting any response out there.
Any idea how to tackle this
Thanks in Advance
Regards
Biju
What I assume you are trying to do is prevent the user from advancing until they receive a valid response from SMS, as some kind of authentication with a timeout of 30 seconds if the response was not received.
To do this, you could display a modal dialog that just displays the "Waiting for SMS Response.." message and close the dialog once 30 seconds have elapsed (using a Timer) or a response is received from SMS.
The event should fire asynchronously, so your program continues. You can have the event handler set a flag to continue on whatever path your program is taking.
also, as a side note, if you ever find yourself thinking "gee, Thread.Sleep(1000) would work great here" take a step back and examine the situation. Most of the time, you can do it asynchronously with events.
It sounds like you could use a timer of some kind. If you need to execute your code within the UI thread, you could use a System.Windows.Forms.Timer; if you're happy with it executing in a thread pool thread you could use System.Threading.Timer or System.Timers.Timer.
I don't know offhand which of these are available in the Compact Framework, but I'd expect at least one of them to be.
If they're really not available, one option which is kinda hacky but would work is to create a new thread which just sleeps for 30 seconds and then either executes the code you need or marshals to the UI thread (using Control.Invoke/BeginInvoke) to execute there if necessary. It's about as crude a timer as you can get, but it should work.