I'm using jQuery to send an AJAX request, retrieving data from a server.
That data is then appended to an element. This should happen 5 times, but it will always happen randomly either 3, 4, or 5 times. Basically, sometimes the loop will skip the AJAX request, but the majority of the time it catches it. How do I make sure it completes the request five times every time? and what is the reason behind this random behavior of skipping AJAX request?(side note. I've checked the request errors, but it never alerted of a request failure)
Here's my JS:
while (counter < 6) {
$.ajax({
url:'http://whisperingforest.org/js/getQuote.php',
async: false,
dataType: 'jsonp',
success:function(data){
$('.quoteList').append('<li>' + data +'</li>');
totalQuotes++;
}
});
counter++;
}
P.s. this happens on a button press.
Don't do it synchronously. Use the callback. Here is a demo for you: http://jsfiddle.net/y45Lfupw/4/
<ul class="quoteList"></ul>
<input type="button" onclick="getData();" value="Go Get It!">
<script>
var counter = 0;
window.getData=function()
{
/* This IF block has nothing to do with the OP. It just resets everything so the demo can be ran more than once. */
if (counter===5) {
$('.quoteList').empty();
counter = 0;
}
$.ajax({
/* The whisperingforest.org URL is not longer valid, I found a new one that is similar... */
url:'http://quotes.stormconsultancy.co.uk/random.json',
async: true,
dataType: 'jsonp',
success:function(data){
$('.quoteList').append('<li>' + data.quote +'</li>');
counter++;
if (counter < 5) getData();
}
});
}
</script>
Setting async to false blocks the main thread (responsible for
executing JavaScript, rendering the screen, etc) and waits for the XHR
to complete.
This is almost always a terrible idea. Users don't like unresponsive
UIs. (https://stackoverflow.com/a/20209180/3112803)
Just search stackoverflow for ajax async: false and you will find MANY good explanations on this. Everyone will discourage you from using async:false. Here's is a great explanation: https://stackoverflow.com/a/14220323/3112803
Very interesting methods provided by jQuery when you are executing loops of asyncroniouse request and detect all ajax request completed or not. It is possible by using
var users=["a","b","c","d","e","f","g","h"];
var async_request=[];
var responses=[];
for(i in users)
{
// you can push any aysnc method handler
async_request.push($.ajax({
url:'', // your url
method:'post', // method GET or POST
data:{user_name: users[i]},
success: function(data){
console.log('success of ajax response')
responses.push(data);
}
}));
}
$.when.apply(null, async_request).done( function(){
// all done
console.log('all request completed')
console.log(responses);
});
Here $.when provides a way to execute callback functions based on zero
or more objects, usually Deferred objects that represent asynchronous
events.
apply() converts array elements as different arguments in
function
$.done is call function after all async. request are
completed.
You can use ES6 async/await Promises like this
function fromServer(){
return new Promise((resolve, reject) => {
$.ajax({
url:'http://whisperingforest.org/js/getQuote.php',
async: false,
dataType: 'jsonp',
success:function(data){
resolve(data)
}
});
})
}
var totalQuotes = 0;
async function domManipulation(){
while (counter < 6) {
var data = await fromServer();
$('.quoteList').append('<li>' + data +'</li>');
totalQuotes++;
}
}
domManipulation()
JSFIDDLE
Related
I need to populate an HTML table using records retrieved via a series of AJAX
requests. The AJAX requests are all generated in a while loop. The total number of requests made is governed by a value provided by the server in a previous exchange of information. The AJAX requests need to be handled asynchronously while the results of the request need to be processed in the order in which originally requested.
The problem, of course is that the responses to the requests do not always
get answered in order. So, after reading up on jquery's Deferred/promise interface I thought I had a solution in hand. But for the life of me can't get my head around how to defer the processing (populating the table) of the results of a requests until the results of previous request(s) have been hanlded. I've found many examples on StackOverflow that get me close, but I can't seem to connect the dots to get it all working in my application.
First I tried using an array of Deferred objects, thinking that I could use indexed references to them to make the processing of one set of records dependent upon the completion of the processing of the previous set (in "as requested" order) set of data. But I couldn't figure out how to create a promise/Deferred object associated with the actual processing of the data - using .then().
var deferreds = [];
var recsPerPkt = 20;
var recRqstd = 0;
while(recsRqstd < totalRecsAvailable) {
console.log("Next record index to request: " + nextNdxRqst)
// Collect an array of the "promise" objects that $.ajax() returns for each call.
deferreds.push( $.ajax({
url: 'eventSummaryData',
type: 'get',
cache: false,
data: {StartNdxNum: nextNdxRqst, NumRecords: recsPerPkt}
}) // End $.ajax({ url: 'trainSummaryData', ...
); // End deferreds.push()
recsRqstd += recsPerPkt;
nextNdxRqst = recsRqstd;
if (deferreds.length > 1)
{
deferreds[deferreds.length - 2].then(
function (jsonData) {
if (jsonData.ok) {
// Now display the rows/records included in this packet.
displayrRecordsInTable({"rows": jsonData.rows});
}
},
function(){
$('#error-msg').text('HTTP error: ' + errorThrown);
}
);
}
}
$.when.apply(null, deferreds).then( function(){
console.log("Processing of AJAX'd data complete. ")
configureTableControls();
});
Then I found a "pattern" that chained the processing functionality using then(),
but the example didn't quite fit my exact situation and ended up having no reference to the http response data in my process-the-data handler. When I run this, the browser logs to the console, "jsonData undefined" .
var prevPromise = $.Deferred().resolve();
var recsPerPkt = 20;
var recRqstd = 0;
while(recsRqstd < totalRecsAvailable) {
prevPromise = prevPromise.then(function(){
return $.ajax({
url: 'eventSummaryData',
type: 'get',
cache: false,
data: {StartNdxNum: nextNdxRqst, NumRecords: recsPerPkt}
});
}).then(function (jsonData) {
if (jsonData.ok) {
// Now display the rows/records included in this packet.
displayTrainSummaryRows({"rows": jsonData.rows});
}
},
function(){
$('#error-msg').text('HTTP error: ' + errorThrown);
}
);
recsRqstd += recsPerPkt;
nextNdxRqst = recsRqstd;
}
So, how can I enforce the processing of AJAX requested data in the sequence in
which the requests were originally made? Thanks in advance.
I would suggest using native Promises over jQuery's deferred objects. They are much more readable, easier to understand, native to the language, and have increasing browser support (with the exception of all IE versions). To account for browser support, use a polyfill like es6-promise and you'll be set. This article does a good job of explaining the basics of promises.
Print results one by one, slower overall
Check out the section of that article I linked to, titled "Parallelism and sequencing" because that really goes in depth on how this works. Essentially you need to create a promise generator function, some sort of mapping for how many ajax requests you need to make (in this case just an array that goes up by 20 each time), and a sequence variable that holds the previous promise that was looped through.
var totalRecsAvailable = 10; //generated elsewhere apparently
var recsPerPkt = 20;
var nextNdxRqst = 0;
var recordRanges = [];
var sequence = Promise.resolve(); //initialize to empty resolved promise
//this generates a promise
function getMyData(startPosition) {
return new Promise(function(resolve,reject){
$.ajax({
type: 'GET',
dataType: 'json',
url: 'eventSummaryData',
data: {StartNdxNum: startPosition, NumRecords: recsPerPkt}
success: function(response){resolve(response);},
error: function(response){reject(response);}
});
});
}
//build out array to inform our promises what records to pull & in which order
for (var i = 0; i < totalRecsAvailable; i++) {
recordRanges.push(nextNdxRqst);
nextNdxRqst += recsPerPkt;
}
//loop through record ranges, chain promises for each one
recordRanges.forEach(function(range) {
sequence = sequence.then(function() {
return getMyData(range); // return a new Promise
}).then(function(data) {
//do stuff with the data
addToHtmlTable(data.something);
}).catch(function(error) {
//something went wrong
console.log(error);
});
});
As outlined in that article, using reduce instead of a forEach is actually a bit better, but I thought this was more clear what was happening.
Wait until all processes resolve, faster overall
For slightly faster performance, you should use Promise.all(). This takes an iterable (like an array) of promises, runs those promises asynchronously, and then saves the results to an array in the order they were passed. If one of the promises fails, the whole thing will fail and give an error. This sounds exactly like what you need. For example, you could do something like this:
var recsPerPkt = 20;
var nextNdxRqst = 0;
var totalRecsAvailable = 10; //generated elsewhere apparently
var promises = [];
//this generates a promise
function getMyData(startPosition, recordsNumber) {
return new Promise(function(resolve,reject){
$.ajax({
type: 'GET',
dataType: 'json',
url: 'eventSummaryData',
data: {StartNdxNum: startPosition, NumRecords: recordsNumber}
success: function(response){resolve(response);},
error: function(response){reject(response);}
});
});
}
//create list of promises
for (var i = 0; i < totalRecsAvailable; i++) {
promises.push(getMyData(nextNdxRqst,recsPerPkt));
nextNdxRqst += recsPerPkt;
}
//This will run once all async operations have successfully finished
Promise.all(promises).then(
function(data){
//everything successful, handle data here
//data is array of results IN ORDER they were passed
buildTable(data);
},
function(data){
//something failed, handle error here
logoutError(data);
}
);
That should set you down the right path.
I don't know of any jQuery function that does what you want, but here is a function processInOrder that will not perform your callback until all previous async ops have resolved while still allowing you to access their results
function processInOrder(arr, cb){
if( arr.length > 0 ){
arr[0].then(function(result){
cb(result);
processInOrder(arr.slice(1), cb);
});
}
}
var deferreds = [];
for(var i=0; i<4; i++){
deferreds.push( asyncRequest(i) );
}
processInOrder(deferreds, display);
Note that while I'm not positive, I'm fairly sure that this form of recursion does not nuke the call stack for large numbers of requests.
Here it is in a jsFiddle
I am relatively a newbie to jquery and ajax and am trying to use the concept of deferrals and promises to solve this problem I have.
I would like to do the following:
Call a list of URLS and process the result returned from the urls. I would like to first process the results in parallel, and then combine the processed results to give me a final result.
Th pseudo-code is as follows:
var deferredAjaxCalls = [];
for (var i = 0; i < jobsListLength; i++) {
deferredAjaxCalls.push(
$.ajax({
url:"/myurl",
method:"POST",
contentType:"application/json",
dataType:"json",
data:mydata,
success:function(result){
//Some code here that is performance intensive
}
});
}
$.when.apply(this,deferredAjaxCalls).done(function(){
for (var k=0; k< arguments.length;k++){
//combine the results of the individual results of the
// success part of all the ajax calls and execute some more
//code synchronously
}
}).fail( function (jqXHR, status, error) {
//Log failed status
});
Initially, I moved all of the code from the success part inside the $.when.apply().However, this resulted in very slow performance as there is a lot of intensive computation that is now executed synchronously. So I am looking for a way to execute part of the code independently, and the final piece synchronously
I did read about using promises, but could not find any example where promises are used with an array of ajax calls with intermediate processing before finally synchronising in the when.apply() block
What would be a good way to solve this problem?
Thanks!
Starting with an array jobsList, you probably want something like this :
var deferredAjaxCalls = jobsList.map(function(job) {
return $.ajax({
url: "/myurl",
method: "POST",
contentType: "application/json",
dataType: "json",
data: mydata
}).then(process);// where `process` is a function that accepts $.ajax's (data, textStatus, jqXHR) and returns a *single* value/object - the result of the processing. This will standardise the data delivered below by $.when() to its success handler.
});
$.when.apply(null, deferredAjaxCalls).then(function() {
// Due to `.then(process)` above, `arguments` are guaranteed to comprise one arg per ajax call.
// Otherwise you potentially have the problem reported here - http://stackoverflow.com/questions/12050160/
for (var k=0; k<arguments.length; k++) {
// Combine the results of the individual results of the success part of all the ajax calls and execute some more code synchronously.
}
// In this function deliver an error by returning `$.Deferred().reject(new Error('myReason'))`
return combined_result;
}, function(jqXHR, status, error) {
// This hander will receive multiple $.ajax() params, which are best normalised into a single Error object.
return new Error(status); // similar to .then(process) above, reduce $.ajax's error args to a single "reason".
}).then(null, function(err) {
// All errors delivered by code above arrive here as a js Error.
// But please note that, in jQuery <v3.0, any uncaught errors above will genuinely throw (to the console).
console.log(err.message);
});
You can try using deferreds:
var req_responses = [];
var deferreds = [];
for(var i in jobs) {
deferreds[i] = new $.Deferred();
}
for(var i in jobs) {
(function(i) {
$.ajax ({
url: ".",
type: "POST",
dataType: "json",
done: function(response) {
//process the response
req_responses[i] = response;
deferreds[i].resolve();
}
});
})(i);
}
$.when.apply(deferreds).then(function(os) {
//all the responses are in req_responses
//finish processing
alert("done");
});
I am trying to write a JS code that will cancel the "btn_submit" buttons .onclick event if the given number already exists in the database. I use AJAX to query the DB for the given number and to determine if the should send the data to a .php site which will upload the question. To determine this I need the numOfRows variable's value, but because I set it in AJAX it will stay on 0. The validation() function will finish before my AJAX query finishes and this causes the problem that will always state that the given number does not exist in the DB (numOfRows will always stay on 0).
How can I await the AJAX query's finish before I compare the numOfRows to 0 in my validation() function's ending lines? If the number already exists in the DB, I need to return false to this line:
document.getElementById("btn_submit").onclick = validation;
Thank you!
var textAreaList;
var numOfRows = 0;
var finished = false;
document.getElementById("btn_submit").onclick = validation;
textAreaList = document.getElementsByClassName("text_input");
function validation() {
loadNumRows();
try {
document.getElementById('failure').hidden = true;
}
catch(e) {
console.log(e.message);
}
textAreaList = document.getElementsByClassName("text_input");
var failValidation = false;
for (var i = 0; i < textAreaList.length; i++) {
console.log(textAreaList[i]);
if (textAreaList[i].value == "") {
textAreaList[i].style.border = "2px solid #ff0000";
failValidation = true;
} else {
textAreaList[i].style.border = "2px solid #286C2B";
}
}
return !(failValidation || numOfRows != 0);
}
function loadNumRows(){
$.ajax({
url: 'php/SeeIfNumberExists?number=' + document.getElementById('number_inp').value,
type: "GET",
cache: false,
success: function (html) {
numOfRows = parseInt(html);
}
});
}
use of async/await with a transpilers like Babel to get it working in older browsers. You’ll also have to install this Babel preset and polyfill from npm:
npm i -D babel-preset-env babel-polyfill
Then
function getData(ajaxurl) {
return $.ajax({
url: ajaxurl,
type: 'GET',
});
};
async function test() {
try {
const res = await getData('https://api.icndb.com/jokes/random')
console.log(res)
} catch(err) {
console.log(err);
}
}
test();
or the .then callback is just another way to write the same logic.
getData(ajaxurl).then((res) => {
console.log(res)
});
Using async: false is an extremely bad idea, and defeats the whole purpose of using AJAX at the first place — AJAX is meant to be asynchronous. If you want to wait for a response from your script when you make the AJAX call, simply use deferred objects and promises:
var validation = function () {
var numberCheck = $.ajax({
url: 'php/SeeIfNumberExists?number=' + $('#number_inp').val(),
type: "GET"
});
// Listen to AJAX completion
numberCheck.done(function(html) {
var numOfRows = parseInt(html),
textAreaList = $('.text_input'),
finished = false;
// Rest of your code starts here
try {
document.getElementById('failure').hidden = true;
}
catch(e) {
console.log(e.message);
}
// ... and the rest
});
}
// Bind events using jQuery
$('#btn_submit').click(validation);
I see in your code that you are using a mixture of both native JS and jQuery — it helps if you stick to one :)
Never use async:false its dangerous, your app might misbehave.
You can use await only when your response returns a promise.
Unfortunately jQuery ajax doesn't return Promise when its completed.
But you can use promise in ajax request and return the promise when its done.
function asyncAjax(url){
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
type: "GET",
dataType: "json",
beforeSend: function() {
},
success: function(data) {
resolve(data) // Resolve promise and when success
},
error: function(err) {
reject(err) // Reject the promise and go to catch()
}
});
});
}
We have converted ajax call into promise so now we can use await.
try{
const result = await asyncAjax('your url');
} catch(e){
console.log(e);
}
this works for me
async function doAjax() {
const result = await $.ajax({
url: "https://api.exchangerate-api.com/v4/latest/USD",
type: 'GET',
});
return result;
}
async function tt(){
var res = await doAjax()
var money = res.rates.INR
console.log(money)
}
tt()
(I acknowledge this is not the best way to go about things, but this is the quickest way to get your code working as is. Really though, you should rethink how you are pulling the numOfRows value so that it will work with truly asynchronous Ajax. All that being said...):
Start by setting async : false in the $.ajax call. The A in Ajax stands for asynchronous. That means, execution continues rather than waiting for it to return. You want to turn that off (i.e. make it synchronous). Actually, that should be the whole solution given the code you have there.
$.ajax({
url: 'php/SeeIfNumberExists?number=' + document.getElementById('number_inp').value,
type: "GET",
async: false,
cache: false,
success: function (html) {
numOfRows = parseInt(html);
}
});
One caveat from the docs for $.ajax:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().
I am looking to fire off several jQuery AJAX requests in quick succession, so the response will not come before the next request. However, I do want to handle each one of these responses with the success function.
With the following code, the first two responses will be ignored and only the last one will respond.
$('#button').click(function() {
var num = 3;
for(var i=0;i<num;i++)
ajaxCall(i);
}
function ajaxCall(data){
$.ajax({
url: '/echo/html/',
success: function(msg) {
alert(msg);
}
});
}
However I am trying to make it so that all three alerts would show up. It seems that each time the ajaxCall function is called it uses the same 'object' as it did the previous time instead of instantiating a new one, which is what I want to do.
Try this (using Deferred Object)
$('#button').click(function() {
var num = 3;
for(var i=0;i<num;i++) {
ajaxCall(i).done(function(data)
{
alert(data)
}
);
}
});
function ajaxCall(data){
return $.ajax({
url: '/echo/html/'
});
}
I have a JavaScript widget which provides standard extension points. One of them is the beforecreate function. It should return false to prevent an item from being created.
I've added an Ajax call into this function using jQuery:
beforecreate: function (node, targetNode, type, to) {
jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
function (result) {
if (result.isOk == false)
alert(result.message);
});
}
But I want to prevent my widget from creating the item, so I should return false in the mother-function, not in the callback. Is there a way to perform a synchronous AJAX request using jQuery or any other in-browser API?
From the jQuery documentation: you specify the asynchronous option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.
Here's what your code would look like if changed as suggested:
beforecreate: function (node, targetNode, type, to) {
jQuery.ajax({
url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
success: function (result) {
if (result.isOk == false) alert(result.message);
},
async: false
});
}
You can put the jQuery's Ajax setup in synchronous mode by calling
jQuery.ajaxSetup({async:false});
And then perform your Ajax calls using jQuery.get( ... );
Then just turning it on again once
jQuery.ajaxSetup({async:true});
I guess it works out the same thing as suggested by #Adam, but it might be helpful to someone that does want to reconfigure their jQuery.get() or jQuery.post() to the more elaborate jQuery.ajax() syntax.
Excellent solution! I noticed when I tried to implement it that if I returned a value in the success clause, it came back as undefined. I had to store it in a variable and return that variable. This is the method I came up with:
function getWhatever() {
// strUrl is whatever URL you need to call
var strUrl = "", strReturn = "";
jQuery.ajax({
url: strUrl,
success: function(html) {
strReturn = html;
},
async:false
});
return strReturn;
}
All of these answers miss the point that doing an Ajax call with async:false will cause the browser to hang until the Ajax request completes. Using a flow control library will solve this problem without hanging up the browser. Here is an example with Frame.js:
beforecreate: function(node,targetNode,type,to) {
Frame(function(next)){
jQuery.get('http://example.com/catalog/create/', next);
});
Frame(function(next, response)){
alert(response);
next();
});
Frame.init();
}
function getURL(url){
return $.ajax({
type: "GET",
url: url,
cache: false,
async: false
}).responseText;
}
//example use
var msg=getURL("message.php");
alert(msg);
Keep in mind that if you're doing a cross-domain Ajax call (by using JSONP) - you can't do it synchronously, the async flag will be ignored by jQuery.
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
For JSONP-calls you could use:
Ajax-call to your own domain - and do the cross-domain call server-side
Change your code to work asynchronously
Use a "function sequencer" library like Frame.js (this answer)
Block the UI instead of blocking the execution (this answer) (my favourite way)
Note: You shouldn't use async: false due to this warning messages:
Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.
Chrome even warns about this in the console:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
This could break your page if you are doing something like this since it could stop working any day.
If you want to do it a way that still feels like if it's synchronous but still don't block then you should use async/await and probably also some ajax that is based on promises like the new Fetch API
async function foo() {
var res = await fetch(url)
console.log(res.ok)
var json = await res.json()
console.log(json)
}
Edit
chrome is working on Disallowing sync XHR in page dismissal when the page is being navigated away or closed by the user. This involves beforeunload, unload, pagehide and visibilitychange.
if this is your use case then you might want to have a look at navigator.sendBeacon instead
It is also possible for the page to disable sync req with either http headers or iframe's allow attribute
I used the answer given by Carcione and modified it to use JSON.
function getUrlJsonSync(url){
var jqxhr = $.ajax({
type: "GET",
url: url,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
function testGetUrlJsonSync()
{
var reply = getUrlJsonSync("myurl");
if (reply.valid == 'OK')
{
console.dir(reply.data);
}
else
{
alert('not valid');
}
}
I added the dataType of 'JSON' and changed the .responseText to responseJSON.
I also retrieved the status using the statusText property of the returned object. Note, that this is the status of the Ajax response, not whether the JSON is valid.
The back-end has to return the response in correct (well-formed) JSON, otherwise the returned object will be undefined.
There are two aspects to consider when answering the original question. One is telling Ajax to perform synchronously (by setting async: false) and the other is returning the response via the calling function's return statement, rather than into a callback function.
I also tried it with POST and it worked.
I changed the GET to POST and added data: postdata
function postUrlJsonSync(url, postdata){
var jqxhr = $.ajax({
type: "POST",
url: url,
data: postdata,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
Note that the above code only works in the case where async is false. If you were to set async: true the returned object jqxhr would not be valid at the time the AJAX call returns, only later when the asynchronous call has finished, but that is much too late to set the response variable.
With async: false you get yourself a blocked browser.
For a non blocking synchronous solution you can use the following:
ES6/ECMAScript2015
With ES6 you can use a generator & the co library:
beforecreate: function (node, targetNode, type, to) {
co(function*(){
let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
});
}
ES7
With ES7 you can just use asyc await:
beforecreate: function (node, targetNode, type, to) {
(async function(){
let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
})();
}
This is example:
$.ajax({
url: "test.html",
async: false
}).done(function(data) {
// Todo something..
}).fail(function(xhr) {
// Todo something..
});
Firstly we should understand when we use $.ajax and when we use $.get/$.post
When we require low level control over the ajax request such as request header settings, caching settings, synchronous settings etc.then we should go for $.ajax.
$.get/$.post: When we do not require low level control over the ajax request.Only simple get/post the data to the server.It is shorthand of
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
and hence we can not use other features(sync,cache etc.) with $.get/$.post.
Hence for low level control(sync,cache,etc.) over ajax request,we should go for $.ajax
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
this is my simple implementation for ASYNC requests with jQuery. I hope this help anyone.
var queueUrlsForRemove = [
'http://dev-myurl.com/image/1',
'http://dev-myurl.com/image/2',
'http://dev-myurl.com/image/3',
];
var queueImagesDelete = function(){
deleteImage( queueUrlsForRemove.splice(0,1), function(){
if (queueUrlsForRemove.length > 0) {
queueImagesDelete();
}
});
}
var deleteImage = function(url, callback) {
$.ajax({
url: url,
method: 'DELETE'
}).done(function(response){
typeof(callback) == 'function' ? callback(response) : null;
});
}
queueImagesDelete();
Because XMLHttpReponse synchronous operation is deprecated I came up with the following solution that wraps XMLHttpRequest. This allows ordered AJAX queries while still being asycnronous in nature, which is very useful for single use CSRF tokens.
It is also transparent so libraries such as jQuery will operate seamlessly.
/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
var xhr = new _XMLHttpRequest();
var _send = xhr.send;
xhr.send = function()
{
/* queue the request, and if it's the first, process it */
XHRQueue.push([this, arguments]);
if (XHRQueue.length == 1)
this.processQueue();
};
xhr.processQueue = function()
{
var call = XHRQueue[0];
var xhr = call[0];
var args = call[1];
/* you could also set a CSRF token header here */
/* send the request */
_send.apply(xhr, args);
};
xhr.addEventListener('load', function(e)
{
/* you could also retrieve a CSRF token header here */
/* remove the completed request and if there is more, trigger the next */
XHRQueue.shift();
if (XHRQueue.length)
this.processQueue();
});
return xhr;
};
Since the original question was about jQuery.get, it is worth mentioning here that (as mentioned here) one could use async: false in a $.get() but ideally avoid it since asynchronous XMLHTTPRequest is deprecated (and the browser may give a warning):
$.get({
url: url,// mandatory
data: data,
success: success,
dataType: dataType,
async:false // to make it synchronous
});