Jquery ajax call inside a then function - javascript

So I need two ajax calls to get all the data. I am using jQuery's ajax call to achieve that. But then I am a bit confused at the execution order. Here is my problematic code:
$.ajax({
type: "GET",
url: "/api/data",
dataType: "json"
}).then(function (data) {
console.log("I am the first")//correct
}).then(function () {
//second ajax
$.ajax({
type: "GET",
url: "/api/lifecyclephase",
dataType: "json"
}).then(function (data) {
console.log("I am the second")//third
})
}).then(function () {
console.log("I am the third")//second
})
The output is
I am the first
I am the third
I am the second
Should not the thenwait for the second ajax to finish its job before proceeding?
The correct one:
$.ajax({
type: "GET",
url: "/api/data",
dataType: "json"
}).then(function (data) {
console.log("I am the first")
}).then(function () {
$.ajax({
type: "GET",
url: "/api/lifecyclephase",
dataType: "json"
}).then(function () {
console.log("I am the second")
}).then(function(){
console.log("I am the third")
})
})

In the problematic code, you are simply missing a return.
$.ajax({
type: "GET",
url: "/api/data",
dataType: "json"
}).then(function (data) {
console.log("I am the first");
}).then(function () {
return $.ajax({
^^^^^^
type: "GET",
url: "/api/lifecyclephase",
dataType: "json"
}).then(function (data) {
console.log("I am the second");
});
}).then(function () {
console.log("I am the third");
});
Without the return, there's nothing to inform the outer promise chain of the inner promise's exitence, hence the outer chain does not wait for the inner promise to settle before proceeding to the third stage.

The "second" $.ajax is initialized within the second .then, but that $.ajax isn't chained with anything else - the interpreter initializes the request and that's it, so when the end of the second .then is reached, the next .then (the third) executes immediately.
Try returning the second Promise instead - a subsequent .then will only wait for a Promise to resolve if that Promise is returned by the previous .then:
.then(function (data) {
console.log("I am the first")//correct
})
.then(function () {
//second ajax
return $.ajax({
// ...

Related

Getting Data from Ajax request displayed

I've already read this article How do I return the response from an asynchronous call? However I couldn't come up with a solution.
I'm doing an ajax request
function getdata(url)
{
console.log('Started');
jQuery.ajax({
type: "GET",
url: "http://myserver.com/myscript.php",
dataType: "json",
error: function (xhr) {
console.log('Error',xhr.status);
},
success: function (response) {
console.log('Success',response);
}
});
}
And Console displays everything fine but when I say
var chinese = getdata();
to get the data. I keep getting:
Uncaught TypeError: Cannot read property 'length' of undefined error for this line
var text = chinese[Math.floor(Math.random()*chinese.length)];
Can anybody help me here?
The problem is that you are using an asynchronous method expecting a synchronous result.
Therefore you should use the code in the result of the asynchronous call like the following:
function getdata(url) {
console.log('Started');
jQuery.ajax({
type: 'GET',
url: url,
dataType: 'json',
error: function(xhr) {
console.log('Error', xhr.status);
},
success: function(chinese) {
var text = chinese[Math.floor(Math.random()*chinese.length)];
// Do something else with text
}
});
}
getData('http://myserver.com/myscript.php');
I hope it helps :)
The error you get is because of the asynchronous nature of the call. I suggest you to assign the value after you get the success response from the API like below.
var chinese = getdata();
Then the function getdata() will be like
function getdata(url)
{
console.log('Started');
jQuery.ajax({
type: "GET",
url: "http://myserver.com/myscript.php",
dataType: "json",
error: function (xhr) {
console.log('Error',xhr.status);
},
success: function (response) {
initChinese(response.data);
}
});
}
And create a function initChinese() like
var text;
function initChinese(chinese){
text = chinese[Math.floor(Math.random()*chinese.length)];
}
You can also declare the text variable in global scope and then assign the value to text variable inside the success function without having to create a new function initChinese.
The problem is your getdata function does not return anything. In your getdata function you're doing a ajax request, which is an asynchronous request. So the data you're requesting won't, and can't be returned with your getdata function.
But you will have the requested data in your success function:
function getdata(url)
{
console.log('Started');
jQuery.ajax({
type: "GET",
url: "http://myserver.com/myscript.php",
dataType: "json",
error: function (xhr) {
console.log('Error',xhr.status);
},
success: function (response) {
console.log('Success',response);
var text = response[Math.floor(Math.random()*response.length)];
}
});
}
As I'm not able to test your code, you've to debug the rest on your own. But the response variable will be most likely your "chinese" variable.
You could try using callbacks or you could look at Promises.
The idea with callbacks is that you pass a function that is run after the ajax request is finished. That callback can accept a parameter, in this case the response.
Using callbacks:
function getData(url, successCallback, errorCallback) {
console.log('Started');
jQuery.ajax({
type: "GET",
url: url,
dataType: "json",
error: function(xhr) {
errorCallback(xhr.status);
},
success: function(response) {
successCallback(response);
}
});
}
var chinese;
getData("http://myserver.com/myscript.php", function(response) {
chinese = response; // you can assign the response to the variable here.
}, function(statusCode) {
console.error(statusCode);
});
Using Promises (< IE11 doesn't support this):
function getData(url) {
return new Promise(function(resolve, reject) {
console.log('Started');
jQuery.ajax({
type: "GET",
url: url,
dataType: "json",
error: function(xhr) {
reject(xhr.status);
},
success: function(response) {
resolve(response);
}
});
});
}
var chinese;
getData("http://myserver.com/myscript.php").then(function(response) {
chinese = response;
console.log(chinese);
}, function(statusCode) {
console.error(statusCode);
});

Working with Ajax Promises / Deferred

I am trying to get an Ajax promise using the code below. Because my function makes another ajax call before initiating the actual one , for getting the authKey, The promise (that should have been returned) from the actual call is null, & I cannot use .then() on it because I think I am not getting anything in return from it. I am not sure why.
What am I doing wrong here? Is there any other way to go about this. I call getAjaxPromise() like mentioned below but get null in return:
getAjaxPromise(myUrl, true, myType, myContentType, mySuccessFunction, myFailureFunction,
myData, true)
.then(function(data) //.then() gives undefined-null error
{
//Do something with the data returned form actual Ajax call.
});
self.getAjaxPromise = function(url, async, type, contentType, successCallback,
errorCallback, data, isSecureCall)
{
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
tokenPromise.then(function(tokenData) { //This then runs fine
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
});
});
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
}
};
you forgot to return the getTokenPromiseFromServer
if isSecureCall is true your function return null
self.getAjaxPromise = function(url, async, type, contentType, successCallback,
errorCallback, data, isSecureCall)
{
if (isSecureCall) {
return getTokenPromiseFromServer().then(function(tokenData) {
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
});
});
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
}
};
You had forgot to return the promise inside the if statement, you are return it only on else, the fixed code below:
self.getAjaxPromise = function(url, async, type, contentType, successCallback,
errorCallback, data, isSecureCall) {
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
tokenPromise.then(function(tokenData) {
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
});
});
return tokenPromise;
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
}
};
You forgot to return tokenPromise
you must return it from first if
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
// ...
return tokenPromise;
}

Multiple Ajax function calls cause slow to load

function function1(val)
{
$.ajax({
type: 'post',
url: 'page1.php',
data: {
get_option:val
},
success: function (response) {
document.getElementById("id1").value=response;
function2(val);
function3(val);
function4(val);
function5(val);
}
});
}
function function2(val)
{
$.ajax({
type: 'post',
url: 'page2.php',
data: {
get_option:val
},
success: function (response) {
document.getElementById("id2").value=response;
function6(val);
}
});
}
function function3(val)
{
$.ajax({
type: 'post',
url: 'page3.php',
data: {
get_option:val
},
success: function (response) {
document.getElementById("id3").value=response;
}
});
}
This is my some functions function1 success part I call other functions like function2, function3, function4, function5. In my Second function function2 I call another one function function6 on its success part its more time to get its resultsHow to avoid this wait time...?
If each of your ajax requests are returning results somewhat sequentially it's probably session blocking in effect. If the execution of the scripts can be performed simultaneously without affecting the results, try adding the following early in the PHP code:
session_write_close(); //let the next requests start
This will allow the subsequent ajax requests to begin PHP processing and should improve your results significantly.

jQuery promise with function

I'm trying to make global ajax handler. so first let me show you the function
var data = {
test : 1
}
$.when( $.ajax({
type: 'POST',
url: ajaxurl,
data : data,
dataType: "json",
success: function(data) {
console.log('first me')
}
})
).then(function( data, textStatus, jqXHR ) {
console.log('then me')
});
this way it works.
and outputs
first me
then me
But I want this ajax to be a function
So this is how I'm trying to make it.
var data = {
test : 1
}
$.when(globalAjax(data)).then(function( data, textStatus, jqXHR ) {
console.log('then me')
});
function globalAjax(data) {
$.ajax({
type: 'POST',
url: ajaxurl,
data : data,
dataType: "json",
success: function(data) {
console.log('first me')
}
})
}
this way console outputs then me and then first me.
How to ask to wait ajax inside a function?
You need to return a promise in globalAjax:
function globalAjax(data) {
return $.ajax({
type: 'POST',
url: ajaxurl,
data : data,
dataType: "json",
success: function(data) {
console.log('first me')
}
});
}
And you don't need to use the $.when function:
globalAjax(data).then(function(data, ...) { ... });
$.when is, mainly, to wait for the completion of two or more deferreds or promises.
function globalAjax(data) {
return $.ajax({
type: 'POST',
url: ajaxurl,
data : data,
dataType: "json",
success: function(data) {
console.log('first me')
}
});
}
you need to return a promise from your function.
$.ajax({
type: 'POST',
url: ajaxurl,
data : data,
dataType: "json",
success: function(data) {
console.log('first me')
}
}).then(function( data, textStatus, jqXHR ) {
console.log('then me')
});
You dont need when $.ajax already returns a promise.
You need to return the ajax promise from globalAjax so that it can be passed to $.when
function globalAjax(data) {
return $.ajax({
type: 'POST',
url: ajaxurl,
data: data,
dataType: "json",
success: function (data) {
console.log('first me')
}
})
}
Demo: Problem, Solution
$.when()
If a single argument is passed to jQuery.when and it is not a Deferred
or a Promise, it will be treated as a resolved Deferred and any
doneCallbacks attached will be executed immediately.
In your case since there is no return from the method, it will pass undefined to $.when which is causing the behavior
since a promise is returned there is no need to use $.when()
globalAjax(data).then(function (data, textStatus, jqXHR) {
console.log('then me')
});
Demo: Fiddle

problems executing a jquery ajax call within a function

I would like to put an ajax call within a function since I use it repeatedly in multiple locations. I want a manipulated version of the response returned. Here's what I'm trying to do (greatly simplified).
a = getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
return response;
});
}
What's happening, however, is that the append function is running before "a" has been defined in the getAjax function. Any thoughts?
AJAX is asynchronous. This means that the code in the success handler is delayed until the request is successful, while the rest of the code continues as normal. You need to put the relevant code in the AJAX success handler:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
$(document.body).append('<div>'+response+'</div>');
});
}
Note that I have also optimised your body selector by using the native Javascript document.body rather than using the standard tag selector.
Edit Callback version
function getAjax(callback) {
$.ajax({
type: 'GET',
url: 'someURL',
success: callback
});
}
You can now do the code inline using a callback function:
getAjax(function(response) {
$(document.body).append('<div>'+response+'</div>');
});
or
getAjax(function(response) {
alert(response);
});
or whatever.
The code inside the anonymous function call will be processed when the AJAX request is complete.
There are two ways to taggle this. one is to use the success callback:
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
the other is to set async to false http://api.jquery.com/jQuery.ajax/:
var a;
getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
async: false,
success: function(response) {
a = response;
});
}
Important note on non async:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Why don't you return the response to another function in the success callback. This should handle your need for different responses:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
}
function AppendResponse(response) {
$('body').append('<div>'+response+'</div>');
}
One suggestion I have is to pass a trigger to the command you want to run into the AJAX function so that it will run after AJAX has received a response-
a = getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
inputText(response);
});
}
inputText(someText) {
$(document.body).append('<div>'+ someText +'</div>');
}
That way you can create if statements / other alternatives to continue to use the same AJAX command for different results
You can give a handler to the function getAjax(), but if the user needs the information for the next decision then why not wait using async: false?
function getAjax(handler) {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
handler(response);
});
};
function callGetAjax(response) {
if(response === undefined) {
getAjax(callGetAjax);
} else {
$('body').append('<div>'+response+'</div>');
}
}

Categories

Resources