I want to make some wine. And my function does:
function wine(){
growGrapes();
process(grapes);
makeWine();
bottle();
}
However, Since my functions often consist of $.ajax() request, some other functions get carried out first. I have used the success tool, but it helps for one ajax request only.
success:function(result){
//Some Code
}
What I actually want is a sequence.
Literally, grapes get processed before growing them. What is a easiest approach?
jQuery Deferred Objects & Promises are the way to go. http://api.jquery.com/category/deferred-object/
They supports running multiple tasks in parallel or series using $.when(PassArrayOfPromisesToRunInParallel) to run processes in parallel and promise.then() to run items sequentially.
Call the next function in the success handler of the $.ajax call of the previous function!
Example:
function growGrapes(){
// lines of code
$.ajax({
success: function(result){
// call next function here - process(grapes); and so on...
}
});
}
The above makes sure the functions get called sequentially after the other..
You can make your Ajax calls synchronous (in sequence) by ensuring you have async: false in your $.ajax() settings.
For example:
$.ajax({ url: 'url',
async: false,
dataType: 'json',
success: function(data) {
}
});
First solution :
Make your ajax call syncronous by setting async : false when setting up your ajax call
$.ajax
({
async : false,
/* other settings */
});
Warning: This solution causes the UI to hand on intensive processing. This should never be used when doing anything rigorous on the server. My recommendation for using this is to only use it in checking flags or loading simple data.
Second solution :
As stated in the comments, use jQuery promises to set up the ordering. Here is a tutorial
I'll try to come back and provide a code example for this solution soon
Third solution :
Make your next call the success handler, or call the next step from the success handler
$.ajax
({
success : NextStep,
/* other settings */
})
One solution is to use queue() function. This way you can execute as many functions as you want
var ajaxQueue = $({});
$.ajaxQueue = function(ajaxOpts) {
// queue the method. a second call wont execute until this dequeues
ajaxQueue.queue(function(next) {
// for this example I serialize params, but you can save them in several variables
// and concat into ajaxOpts.data
var params = method_that_get_params_and_serialize_them();
ajaxOpts.data = params;
ajaxOpts.complete = function() {
next();
};
$.ajax(ajaxOpts);
});
};
then your functions should be like this:
function growGrapes(){
$.ajaxQueue({
cache: false,
type: "POST",
url: "someUrl",
dataType: "json",
data: "", // we fill data inside ajaxQueue() method
success: function( response) {
//do things with response
}
});
}
If you want to keep it tidy and clean to let people see how your calls are made, you can simply pass a callback function to another like this:
function growGrapes(callback) {
$.ajax({
...
success: function (){
// Something
if (typeof callback === typeof Function) callback();
},
...
});
}
function wine(){
growGrapes(function (){
process(grapes);
});
}
Related
I've some simple ajax calls to populate drop down lists:
window.addEventListener('load', function () { GetDropDownData('http://mysite/controller/action/parameters1', '#ddl1') });
..
window.addEventListener('load', function () { GetDropDownData('http://mysite/controller/action/parameters4', '#ddl4') });
$.ajax({
url: url,
cache: true,
crossDomain : true,
dataType: 'jsonp',
type: "GET",
success: function (data) {
$(id).html(data);
},
error: function (reponse) {
$(id).html("error : " + reponse.responseText);
}
});
if I use them individually are fast, but used together are slow. This is evident in the images below.
The first time I use 1 call and it is fast, the second time I use 2 calls and the previous becomes slow now. The same with multiple calls.
Why this? And, can I solve it avoiding to merge the calls in a single call?
Session locking? One call comes in, locks the session, the second has to wait for the first to finish
Try switching session off and see if it improves
(I had the same problem once)
NB This answer only applies if the calls are asynchronous (as per the other comment)
http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/
I'm writing piece of code, and I need some functions to be executed sequential, I used ajax call but it is asynchronous and i faced problems
function GetLibraryActivities(libraryName, callback) {
$.ajax({
dataType: "json",
url: "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName
}).done(function (data) {
console.log(data);
return data;
});
}
then I tried to work with callback function, but it didn't work too.
function GetLibraryActivities(libraryName, callback) {
$.ajax({
'url': "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName,
'type': 'GET',
'success': callback
});
}
GetLibraryActivities("Petrophysics", function (data) {
petrophysicsData = data
});
when I try to use petrophysicsData variable under the code it returns unidentified , I need a mean to call a function in synchronous way, any help will be appreciated thanks.
Your main problem here is that you are trying to 'return' something from an AJAX callback. You cannot expect an Async AJAX function to return values to the script function that called it, because the function that called it moved on after the AJAX call started. That is the point of an Async call, it allows the javascript to move on and not have to wait for the server communication to complete.
The best way to handle this is to call all portions of a function in sequential order by using callbacks, never planning to use a return.
So, rather than returning data it would be best to instead call a function that processes data from within the callback function. It can be a little inconvenient, but when working with Async calls, it is best to assume that you can only go deeper into your call stack, rather than returning anything back out of it.
So, rather than your first option...you would want to do something like this instead...
function GetLibraryActivities(libraryName, callback) {
$.ajax({
dataType: "json",
url: "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName
}).done(function (data) {
console.log(data);
ProcessResults(data);
});
}
Or, simply perform your processing within the callback.
Pre jQuery 1.8, there was the 'async' option, that would allow you to force Javascript to wait for the ajax call to process...but this locks up the browser while it is processing, and has since been deprecated.
If you simply return the Ajax promise like this:
function GetLibraryActivities(libraryName, callback) {
return $.ajax({
'url': "/WorkflowDesigner/GetLibraryActivities/?libraryName=" + libraryName,
'type': 'GET'
});
}
you can do this to use the value:
GetLibraryActivities("Petrophysics").done(function (data) {
// do something with petrophysics data
});
and chain them "sequentially" with then like this:
GetLibraryActivities("Petrophysics").then(GetLibraryActivities("Astrophysics")).done(function(pertro, astro){
// Do something with both results};
});
In this example both will load in parallel, but the done will only be called with both promises have completed (in any order).
If you have loads of these to load, you can use $.when to process multiple promises.
I am wondering is these is any way to access the results of a jquery ajax call in the form a traditional var set to function fashion. For example consider:
function getPoints(){
//An array of JSON objects
var Points;
$.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
}).done(function(data){
//console.log(data);
Points.append(data);
});
console.log(Points);
return Points;
}
The commented out console.log show the array of json objects whereas the outer one does not. Now, i have tries this:
var Points = $.ajax({ ...});
And i see the response text within a larger object, but am unsure how to access the responseText. console.log(Points.responseText) yields an undefined variable.
Is this possible with this approach? Here is another question that received a check mark with a similar issue.
I have another solutions, which is the encapsulate my code within the done() function and i will have access to all my data. I was just curious if what i am attempting to do is even doable.
Thank you.
yes it is possible, however, you must wait for the request to be complete before doing so. However, since you can't effectively force the return to wait until the data exists, you're only options are to return a deferred object instead, or re-write the function in such a way that allows it to accept a callback.
function getPoints(){
return $.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST'
});
}
getPoints().done(function(data){
console.log(data);
});
or
function getPoints(callback){
return $.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
success: callback
});
}
getPoints(function(data){
console.log(data);
});
Because the Ajax call is done asynchronously you shouldn't return it from the outside function. This would require that you somehow block until the asynchronous call completes. Instead you could pass in a callback function to the getPoints function that will handle the logic of using the points.
function getPoints(callback){
$.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
}).done(function(data){
callback(data);
});
}
The asynchronous nature of ajax can make things harder if your used to imperative programming, but it will make your user interface much more responsive.
The log you're calling in the outer function is working with an undefined variable because the function is asynchronous. You can't return it from getPoints because it won't have finished. Any work with the Points variable needs to happen inside the callback (the function passed to done).
I'm trying to create a variable from the result of a jsonp request, and the use this variable later in the script. But it seems like the part where the variable is used is triggered before the jsonp request is done.
function onSuccess(data) {
var result = data['result'];
console.log(result);
}
function onError(data) {
alert(data);
}
$.ajax({
url:"http://suneeriksen.unboxer.org/",
cache: false,
dataType: 'jsonp',
jsonp: 'callback',
timeout: 5000,
success: onSuccess,
error: onError
});
var gallery,
el,
i,
page,
dots = document.querySelectorAll('#nav li'),
slides = result //this is where I try to fetch the variable
];
I've tried to figure out how this could be done. I've tried to put the jsonp request in a function and done like this:
var slides = jsonpResult();
Any clue what to do?
EDIT:
I also have functions using the gallery variable
gallery.onFlip(function () {
//Doing stuff
}
And I can't put all of these in the onSuccess function.
Bind it for onSuccess - don't call the function that uses it until onSuccess occurs.
You could also force your request to be synchronous (no code will execute until your ajax has run) but I highly recommend you don't.
There are two ways:
Make the AJAX call not A(synchronous) by setting async: true at the ajax call options (please note that this approach is now deprecated).
or:
do call whatever code that uses the slides variable from inside the success callback (and do the assigning there as well, if you need it for future use).
Similar to the question I just asked,
If I call an ajax function in jQuery and then a non ajax function how can I prevent the non-ajax function from firing until after the first ajax callback function has completed. Will declaring async: false in the first ajax function be enough?
If you're talking about this:
$.ajax({...});
someFunction();
where someFunction() won't occur until the AJAX call completes then you have three options:
Make the AJAX call async: false. Don't do this. It'll make your page unresponsive;
Put someFunction() in the complete/success/error callbacks of the AJAX call. This is the recommended approach; or
Use aplugin to manage a request queue eg Ajax Queue.
The first A in AJAX stands for "asynchronous". You just need to get used to the fact that these calls are asynchronous and stop trying to force a synchronous programming model on top of them. Adapt to the new programming model.
jQuery AJAX functions let you provide a callback that is only called after the request is finished. Call your non-ajax function as part of that callback.
You can use callback functions like this:
$("#btnSample").on("click", function (e) {
$.ajax({
url: 'some_url',
type: "GET",
async: true,
cache: false,
dataType: "JSON",
data: {
"p1": v1,
"p2": v2
},
success: function(result) {
//call you second function here!
}
}
});
});