Delaying a setTimeout() - javascript

I'm having an issue with some asynchronous JavaScript code that fetches values from a database using ajax.
Essentially, what I'd like to do is refresh a page once a list has been populated. For that purpose, I tried inserting the following code into the function that populates the list:
var timer1;
timer1 = setTimeout([refresh function], 1000);
As you might imagine, this works fine when the list population takes less than 1 second, but causes issues when it takes longer. So I had the idea of inserting this code into the function called on the success of each ajax call:
clearTimeout(timer1);
timer1 = setTimeout([refresh function], 1000);
So in theory, every time a list element is fetched the timer should reset, meaning that the refresh function should only ever be called 1 second after the final list element is successfully retrieved. However, in execution all that happens is that timer1 is reset once, the first time the second block of code is reached.
Can anybody see what the problem might be? Or if there's a better way of doing this? Thanks.
==========
EDIT: To clear up how my ajax calls work: one of the issues with the code's structure is that the ajax calls are actually nested; the callback method of the original ajax call is itself another ajax call, whose callback method contains a database transaction (incorrect - see below). In addition, I have two such methods running simultaneously. What I need is a way to ensure that ALL calls at all levels have completed before refreshing the page. This is why I thought that giving both methods one timer, and resetting it every time one of the callback methods was called, would keep pushing its execution back until all threads were complete.
Quite honestly, the code is very involved-- around 140 lines including auxiliary methods-- and I don't think that posting it here is feasible. Sorry-- if no one can help without code, then perhaps I'll bite the bullet and try copying it here in a format that makes some kind of sense.
==========
EDIT2: Here's a general workflow of what the methods are trying to do. The function is a 'synchronisation' function, one that both sends data to and retrieves data from the server.
I. Function is called which retrieves items from the local database
i. Every time an item is fetched, it is sent to the server (ajax)
a. When the ajax calls back, the item is updated locally to reflect
its success/failure
II. A (separate) list of items is retrieved from the local database
i. Every time an item is fetched, an item matching that item's ID is fetched from the server (ajax)
a. On successful fetch from server, the items are compared
b. If the server-side item is more recent, the local item is updated
So the places I inserted the second code block above are in the 'i.' sections of each method, in other words, where the ajax should be calling back (repeatedly). I realize that I was in error in my comments above; there is actually never a nested ajax call, but rather a database transaction inside an ajax call inside a database transaction.

You're doing pretty well so far. The trick you want to use is to chain your events together, something like this:
function refresh()
{
invokeMyAjaxCall(param1, param2, param3, onSuccessCallback, onFailureCallback);
}
function onSuccessCallback()
{
// Update my objects here
// Once all the objects have been updated, trigger another ajax call
setTimeout(refresh, 1000);
}
function onFailureCallback()
{
// Notify the user that something failed
// Once you've dealt with the failures, trigger another call in 1 sec
setTimeout(refresh, 1000);
}
Now, the difficulty with this is: what happens if a call fails? Ideally, it sounds like you want to ensure that you are continually updating information from the server, and even if a temporary failure occurs you want to keep going.
I've assumed here that your AJAX library permits you to do a failure callback. However, I've seen some cases when libraries hang without either failing or succeeding. If necessary, you may need to use a separate set of logic to determine if the connection with the server has been interrupted and restart your callback sequence.
EDIT: I suspect that the problem you've got is a result of queueing the next call before the first call is done. Basically, you're setting up a race condition: can the first call finish before the next call is triggered? It may work most times, or it may work once, or it may work nearly all the time; but unless the setTimeout() is the very last statement in your "response-processing" code, this kind of race condition will always be a potential problem.

Related

How can I update DOM while a method is running?

I'm writing a simple tool that works on the client side. Basically, the user brings in a file, presses a button to start it, it does stuff with it (takes about 10-15 seconds), and then it gives the modified file back.
Unfortunately, as soon as they press the button to start the method, the DOM doesn't update until the method is finished, so there's no feedback until it's all finished, which is quite frustrating.
In the template section, I have:
<p v-if="processingStatus==1">Processing data...</p>
The "processingStatus" variable is set to 0 by default.
In the method, which is "processData" and is called when the button is pressed, it starts with
this.processingStatus = 1
And then proceeds to process the data.
Unfortunately, the "Processing data..." tag doesn't show up until the method is finished. How can I force VueJS to render the DOM while the method is running?
Based on what you are saying that processData is doing (going through a bunch of data in arrays), my guess is that it is not running async and is locking the javascript thread until it is done.
What you need to do is inside processData is set the is processing variable like you are, but then do all the actual work inside a promise or some other mechanism to release control and update the UI.
Potentially you could also call
vm.$forceUpdate();
before starting all your array work.

Wrapping AJAX in a function seems to make it lose async?

I have a script I'm using to schedule resources using an API and a list in CSV format. The script currently loops through the CSV and fires off a call to a function that has the API calls in it. The AJAX calls are nested (Create a Reservation->Take the reservation number and add a resource->Validate the reservation->Submit the reservation). The problem is that after the original AJAX call, it seems to hang until all of the AJAX calls have completed. There doesn't seem to be any asynchronicity going on.
for(line in CSV)
{
makeAPICalls(line)
}
function makeAPICalls(line)
{
$.ajax("Create Reservation").then(function(){
$.ajax("Add Resource to Reservation").then(function(){
$.ajax("Validate Reservation").then(function(){
$.ajax("Confirm Reservation")
})
})
})
}
The first API call ("Create Reservation") completes, and then waits for all of the other lines in the CSV to make that call, then they ALL move on to the next step ("Add Resource to Reservation"). I was wondering if the system was just moving too quickly, so there wasn't a chance for everything to get "out of sync", so I added a delay before makeAPICalls(), but it still waited. Once the CSV loop finished, all the AJAX calls moves from ("Create Reservation") to the then("Add Resource to Reservation").
Is this as expected? Ideally I'd like each call to makeAPICalls() to finish as quickly as possible, with no regards for any other calls (which I kind of thought was what async was all about, but it doesn't seem to be happening here.
This is happening because you are chaining the requests. If your requests are not dependent on each other, you can call them without using .then().
The behaviour is quite correct. I don't know how you are putting in the delay but it probably won't help since JavaScript is single-threaded.
If you want all the steps to complete for a specific csv line you could have your function process the list one-by-one. You could even have the last step call back into the function with the next index to process.

How to refresh screen data in JavaScript without making the page slow?

I have a question in terms of code and NOT user experience, I have the JS:
$(document).on( "click", "input:radio,input:checkbox", function() {
getContent($(this).parent(),0);
});
The above JS gets the contents from radios and checkboxes, and it refreshes the page to show dependencies. For example if I check on yes, and the dependency is on yes, show text box, the above works!
What I want to know is, if there is a better way to do the same thing, but in a more friendly way, as this is at times, making the pages slow. Especially if I do a lot of ticks/checks in one go, I miss a few, as the parent refreshes!
If you have to hit your server to getContent() then it will automatically be slow.
However, you can save a lot if you send all the elements once instead of hitting the server each time a change is made.
Yet, if creating one super large page is not an option, then you need to keep your getContent() function, but there is one possible solution, in case you did not already implement such, which is to cache all the data that you queried earlier.
So you could have an object (a map) which has keys defining the data you're interested in. If the key is defined, then the data is already available and your return and use that data directly from the cache. Otherwise, you have to hit the server.
One thing to do, you mentioned slowness as you 'tick' things back and forth, is to not send more than one request at a time to the server (with a timeout in case the server never replies). So the process here is:
Need data 'xyz'
Is that data already cached? if yes, then skip step (3 and 4)
If a request being worked on? if yes, push the data on the request stack and return
Send a request to the server, which blocks any further request until answer for 'xyz' is received
Receive the answer and cache the data in an object (map) and release the request queue
Make use of data as required
I check the request queue, if not empty pop the next request and start processing from (2)
The request process is expected to be run on a timer because (1) it can time out and (2) it need to run in the background (not GUI preemptive)

How to organise many ajax requests self dependent

I am trying to write an app in JS. It will store data in one object through many ajax calls to other site.
So, I make a call, receive some data and put it in a variabile. Then I do other call using previus data. There will be many calls based on previus data.
I did some functions for every call and tryed to execute them one by one, but I see that when next function is executed the previus one may not be finished yet and data is not available.
I know that there are callback functions, but I can't make every next function to be called by callback from previus one, because I need to run or not some of them depending on data.
Please help me, tell me how to organise my app or tell me where to read about it. I even don't know what to write to google to find what I need.
You are making ajax request, but ajax request are not syncronous, then you need to use callback inside your functions to control when a function was finished.
You can use some jquery functions that encapsulate this so you can made any effort to have the same behavior.
You need to create an array of function that are not dependent of any data or other functions:
var deferreds = [];
$.each(views, function(index, view) {
deferreds.push($.get('url_that_you_want_to_call', function(data) {
// treat your data as you wish
}));
});
Then you can pass this array to be executed and you can control when they are finished:
$.when.apply(null, deferreds).done(callback);
You need to repeat this process until all your request are done.
This answer was helpful

Any issue with setTimeout calling itself?

I have read a handful of setTimeout questions and none appear to relate to the question I have in mind. I know I could use setInterval() but it is not my prefered option.
I have a web app that could in theory be running a day or more without a page refresh and more than one check a minute. Am I likely to get tripped up if my function calls itself several hundred (or more) times using setInterval? Will I reach "stack overflow" for example?
If I use setInterval there is a remote possibility of two requests being run at the same time especially on slow connections (where a second one is raised before the first is finished). I know I could create flags to test if a request is already active, but I'm afraid of false positives.
My solution is to have a function call my jquery ajax code, do its thing, and then as part of ajaxComplete, it does a setInterval to call itself again in X seconds. This method also allows me to alter the duration between calls, so if my server is busy(slow), one reply can set a flag to increase the time between ajax calls.
Sample code of my idea...
function ServiceOrderSync()
{
// 1. Sync stage changes from client with the server
// 2. Sync new orders from server to this client
$.ajax( { "data": dataurl,
"success": function(data)
{ // process my data },
"complete": function(data)
{
// Queue the next sync
setTimeout( ServiceOrderSync, 15000 );
});
}
You won't get a stack overflow, since the call isn't truly recursive (I call it "pseudo-recursive")
JavaScript is an event driven language, and when you call setTimeout it just queues an event in the list of pending events, and code execution then just continues from where you are and the call stack gets completely unwound before the next event is pulled from that list.
p.s. I'd strongly recommend using Promises if you're using jQuery to handle async code.

Categories

Resources