My server-side Blazor app calls multiple times a javascript function that is supposed to move a div around (using setInterval).
The issue is that the function does not wait for the previous call to finish. As a result, the DOM is changed from different js interops at the same time which leads to unpredictable results. I was expecting the calls to be stacked up and run one by one.
Do you have an idea how can I solve this issue? Thanks a lot!
Seems like the only way is to use custom data attributes on the DOM as a lock.
Something like that: data-lockincrement="0"
Each JSInterop call should include that lockincrement so Setinterval continues until lockincrement matches the value which means the calls will be executed sequentially.
Related
I'm trying to think the best practice for this use case:
I have an internal state: results[] that will be used for displaying data in render.
Then, I need to call 3 API's, in parallel, and then merge and sort them into results[] before finally rendering it.
I'm using axios to call the API's, but i don't want to use axios.all because i need to display the results[] as each of the 3 apis are returning, that way, it looks faster.
Im running into problem because everytime i update results[] with new data using this.setState(), the latter operation always see the old results[]; this.setState() doesn't immediately get applied..
What's the best way to do this?
There will never be a race condition since Javascript runs on a single thread. It is guaranteed that only one asynchronous callback will run at any one time, since a single thread cannot execute both at once. The next asynchronous callback will be scheduled to run later. Within one function call, you can be assured that you are the only one working on some data.
Data may come in at different times, but if you simply merge and sort the data every time you receive new data, that will be atomic.
I am kind of new to javascript.
This is not a website scenario, but android webview with local javascript and html, css ist still used.I am trying to figure out the total length of ebook, which comprises of n html documents.
What I am doing is I use n AJAX requests to request local file, which in the callback I append to the current document and calculate document length (via element.scrollWidth, which then seems to trigger the actual layout and can take several seconds -- for every request, heavy work)
Now I might need to cancel this whole operation.
BUT
As Ive learnt javascript uses event queue, so while AJAXes are parallel, the callbacks are synchronous. So in my case AJAXes are fast but callbacks take long. Here lies the problem. When I call my cancel() from android, that is just put onto the event queue, defacto after all the callbacks, so there is no way this cancel method can do anything to the already event loop queued up callbacks, like changing some cancel = true global variable, even aborting does nothing since all the ajaxed returned, just callbacks are waiting in the queue.
Is there a way to cancel this? Or do I need a totally differnt approach? (My guess is no, since in java that cancel method, and the processing would run on different threads, here in JS everyhing ran on single thread)
I have seen a lot of function examples for async javascript containing setTimeout, AJAX calls, etc.
Obviously these all have a certain delay meaning the flow of the script is impacted. But I was wondering, what if I have something like this:
function init() {
this.initSlider();
this.testLog();
}
function initSlider() {
// find multiple items and build up a slider instance
// for each of these elements.
}
function testLog() {
console.log('test);
}
If initSlider possible takes a long time will it simply run my testLog function first?
I am currently a bit unsure about this. I know there might be plenty of examples on the flow of javascript but I can't find ones where a simple function would just take a longer time to run.
It is totally depend on what is there inside initSlider(). Although initslider() is heavy function and do not contain any asynchronus statement
then testLog() will not execute first.
Javascript stores all statements in callstack and they will be executed one after the other.
If there is asynchronus statement then it removes that statement outof the callstack and there is chance of your testLog() to execute.
so for your question my answer will be DEPENDS ON CODE INSIDE initSlider()
Javascript is a technology that runs single threaded. When you use asynchronous methods like AJAX or setTimeout the javascript engine processes those parts one by one (if one is waiting something than switching to another and then back and etc...). You can see the javascript's power on async tasks with Node.js. I guess this blog is very good to understand the Javascript and async methods: click_me!
I have noumerous ajax calls on page Load and those calls bring neseesary resources to start application (JSON massives and functions).
The problem is, that those resources get loaded not strictly on after another, but asynchroniusly and before get in used they get formatted by success functions.
To start application a have to check that all resources loaded and have been formatted properly. The best way to do this I found is to run circle with timeOut, checking all of them unless all are ready. It doesn't seem right for me, couse it takes a while to start application, so I thought that may be there is another appoach.
I thought about getting setInterval function with a little timeout and a bunch of nested IF's, and at the end of those IF's I could cancel Interaval functin and start application.
May be soneone is familiar with right approach to such things and could share some code?
I know I can get Selenium 2's webdriver to run JavaScript and get return values but so much asynchronous stuff is happening I would like JavaScript to talk to Selenium instead of the other way around. I have done some searching and haven't found anything like this. Do people just generally use implicitly_wait? That seems likely to fail since it's not possible to time everything? Perfect example would be to let Selenium know when an XHR completed or an asynchronous animation with undetermined execution time.
Is this possible? We're using Selenium 2 with Python on Saucelabs.
You should look into the execute_async_script() method (JavascriptExecutor.executeAsyncScript in Java, IJavaScriptExecutor.ExecuteAsyncScript() in .NET), which allows you to wait for a callback function. The callback function is automatically appended to the arguments array in your JavaScript function. So, assuming you have a JavaScript function already on the page that waits until the condition you want, you could do something like the following (Java code below, C# and Python code should be similar):
String script = "var callback = arguments[arguments.length - 1];"
+ "callback(myJavaScriptFunctionThatWaitsUntilReady());";
driver.manage().timeouts().setScriptTimeout(15, TimeUnit.SECONDS);
((JavascriptExecutor)driver).executeAsyncScript(script);
It might be possible to be even more clever and pass the callback function directly to an event that returns the proper data. You can find more information on the executeAsyncScript() function in the project JavaDocs, and can find sample code for this in the project source tree. There's a great example of waiting for an XHR to complete in the tests in this file.
If this isn't yet available in the version of the Python bindings available for use with SauceLabs, I would expect it to be available before long. Admittedly, in a sense, this is pushing the "poll for desired state" from your test case into JavaScript, but it would make your test more readable.
Theoretically it is possible, but I would advise against it.
The solution would probably have some jQuery running on the site that sets a variable to true when the JavaScript processing has finished.
Set selenium up to loop through a getEval until this variable becomes true and then do something in Selenium.
It would meet your requirements but it's a really bad idea. If for some reason your jQuery doesn't set the trigger variable to true (or whatever state you expect) Selenium will sit there indefinetly. You could put a really long timeout on it, but then what would be the different in just getting Selenium to do a getEval and wait for a specific element to appear?
It sounds like you are trying to overengineer your solution and it will cause you more pain in the future will very few additional benefits.
Not to be overly blunt, but if you want your App to talk to your Test Runner, then you're doing it wrong.
If you need to wait for an XHR to finish, you could try displaying a spinner and then test that the spinner has disappeared to indicate a successful request.
In regards to the animation, when the animation has completed, maybe its callback could add a class indicating that the animation has finished and then you could test for the existence of that class.
Testing animation with selenium is opening a can of worms. The tests can be quite brittle and cause many false positives.
The problem is to do that the calls are asynchronous, and difficult to track the behaviour and change in state of the page.
In my experience the asynchronous call can be so quick that the spinner is never displayed, and the state of the page may skip a state entirely (that Selenium can detect).
Waiting for the state of the page to transition can make the tests less brittle, however the false positives cannot be removed entirely.
I recommend manual testing for animation.