How to organise many ajax requests self dependent - javascript

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

Related

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.

Delay required in between the execution of two statements

i am working with extjs 4.2 and at one place i am loading the store object like this :
var userDetailStore = Ext.create('Ext.data.Store', {
model : 'Person.DetailsModel',
autoLoad : true,
proxy : {
type : 'ajax',
method : 'POST',
url : 'getValueAction.action',
reader : {
type : 'json',
root : 'details'
},
writer : {
type : 'json',
root : 'details'
}
},
fields : ['id','loginName','referenceId' ,'name']
});//Here I load the store which will definitely contain a list of values.
and in the very next line i want to get the referenceId of the first value from the store object like this
var empId = userDetailStore.getAt(0).get('referenceId')
and i am getting the error because till now the getCount() of the store object userDetailStore is giving me zero.But if i write an alert statement like alert('loading data'); before the line where i am getting the referenceId then the code works fine.The line userDetailStore.getCount() is giving me the exact value.
So i think some kind of delay is required between the loading the store and then using the store but I don't want an alert to show.I have even used the sleep() method in place of alert statement.But that is also not working.(BTW i don't even want to freeze the browser by executing the sleep())
Am i doing anything wrong while loading the store ?Is there any general way so that i will execute my code for using the store after the store is completely loaded ?
Somebody please help me out here...
Regards :
Dev
Vijay's answer is correct, but I thought I'd expand on the concept so that it's clear how this answer fits into what you're doing.
It's important to understand that when you make an AJAX request, the request is asynchronous. What this means in practical terms is that (as you found out) the remainder of your calling script does not wait for the asynchronous process to complete. Rather, the moment that you make an asynchronous request, your script is going to continue on it's merry way, executing the very next line of code.
So if you think about it, this makes perfect sense why you were not seeing a "count" in your store. While your async request was in the process of going to the server, getting the result, and then returning it to your request, the rest of your code kept right on executing, oblivious to what was happening in the async request (and this is precisely why async requests are powerful and awesome).
This is also why adding the alert seemed to "fix" your problem. When you call alert(), you literally halt execution of your script at the point of the alert. However, since your request for data was asynchronous, the time it took you to click the "OK" button of the alert (and hence resume processing of your script) gave the async request enough time to complete its lifecycle and update the original calling object.
In light of this, it's understandable why it would seem that a "delay" would be a desirable way to go, since the "delay" (or really, "halting") of the alert fixed your issue (at least on the surface). However, with async requests, you can never really know how long it's going to take to complete. If you have a large response, or there is unusual network latency, or any other number of issues...the hard-coded delay might work, but it also might not. Most maddening of all is that you'd never get consistent results, and would constantly be increasing the "delay" in order to accomodate all the things that could contribute to your async request taking longer and longer.
This is why the load() event of the store (and callbacks in general) is such a critical concept to understand and implement. By listening for the load() event, and then executing what code you need only within the context of that event firing, you can know for sure that the store's async request for data has completed.
If you've not used callbacks and event handling before, it does take a bit of getting used to in order to break out of the linear, procedural mindset. However, when dealing with AJAX requests in general, and event-driven frameworks like ExtJS 4 in particular, it's a concept you need to embrace in order to build effective and consistent applications.
use on load event to get the count after it's fully loaded
userDetailStore.on('load', function(){
alert("Fully loaded");
});
Here set autoload to false and on some action you can use load() to load your store.
store.load({
callback: function(records, operation, success) {
// do something after the load finishes
},
scope: this
});

Using Data Generated from AJAX Call for OnClick Event

I have a web application where I want to get some data from an API right when the document is ready to execute javascript. I want to store this data in an Object for later access. When a user clicks on a certain link on the page, I will need access to this Object.
I'm wondering what the safest/most accepted pattern for achieving this is, since it involves to events to listen for (the success of the AJAX request and the later possible click). I don't really want to wrap all of my code in the AJAX request if I don't have to, but I also don't want to run the risk of the user clicking before the AJAX request has finished (it's a fairly small API call, but still).
Deferred objects to the rescue!
(function($){ // this prevents polluting the global scope
var request = $.ajax({...});
//... later on...
$(someelement).on("click",function(){
request.done(function(data){
console.log(data);
});
});
})(jQuery);

Delaying a setTimeout()

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.

Check if a javascript has loaded and then call another javascript

I have a javascript which gets JSON data from URL and loads the data on to the page, then I want to call another javascript to add the slide effects.
There is a simpler solution, i.e using setTimeout. But this solution is not complete because getting data from a URL does not have a fixed amount of time. It varies on every call.
Hence I want to check if my first javascript has loaded and then I want to call the second javascript.
JavaScript is an asynchronous language, or at least, its HTTP API is (mostly) asynchronous.
You shouldn't use settimeout, but you should use asynchronous chaining instead for building a list of causal events. There's a big bunch of libraries out there to assist this, like http://www.infoq.com/articles/surviving-asynchronous-programming-in-javascript
If you're loading content from your own site, then there'll be an onsuccess/oncomplete event when the JSON finally gets loaded, you can assign a callback to it. How it is actually called depends on your javascript framework if you use one.
If you're using data from a remote site in a format called JSONP, you're to define a callback to it, it should be a public function name, like onMyDataArrived. You should add your callback code there. Some frameworks hide this detail from you, they generate a random function which they remove when the data has arrived, and provide an API similar to onSuccess / onComplete instead.
Nowadays, the most popular javascript framework is jQuery, where you can do such things, like:
$.ajax({
url: 'give_me_my_json.php',
dataType: 'json',
success: function(data){
//call your second javascript
},
error: function(){
//WHOOOPSIE... data could not be loaded
}
});

Categories

Resources