I've been trying to figure this one out since my earlier question.
I can receive the data, as I see it under resources using Develop > Show Web Inspector on safari. But I can't seem to assign it successfully to a variable to use later on.
<script>
function getData () {
$.ajax
({
type: "GET",
url: "https://myjirasite.com/jira/rest/api/2/project/ON/versions?",
dataType: 'jsonp',
//async: true,
beforeSend: function (xhr) {xhr.setRequestHeader('Authorization', make_base_auth("myusername", "mypassword"));},
success: function (){
//Attempt 1 at outputting the result to an alert.
alert(JSON.parse(data));
}
});
}
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return 'Basic ' + hash;
}
</script>
In a second attempt I assign the ajax call to a variable and attempt to print that out to an alert. No success. the alert is empty
var jqXHR = $.ajax
({
type: "GET",
url: "https://myjirasite/jira/rest/api/2/project/ON/versions?",
dataType: 'jsonp',
async: false,
beforeSend: function (xhr) {xhr.setRequestHeader('Authorization', make_base_auth("myusername", "mypassword"));},
success: function (data){
alert(JSON.parse(data));
}
});
alert(JSON.parse(jqXHR.responseText));
I know that the issue lies with ajax calls being asynchronous, but I can't figure out how to write the callback such that I can get the json data into a variable to use later in via a different function.
Don't set async: false, as this will block the browser whilst your Ajax request is processed.
Instead, you can use promises, or call a further function from within your success callback.
Something like:
function getData(){
return $.ajax({
type: "GET",
url: "https://myjirasite/jira/rest/api/2/project/ON/versions?",
dataType: 'jsonp',
beforeSend: function(xhr){
xhr.setRequestHeader('Authorization', make_base_auth("myusername", "mypassword"));
}
});
}
getData()
.done(function (data){
console.log(JSON.parse(data));
})
.fail(function(){
console.log("Error!");
});
<script>
var getData = function() {
$.ajax
({
type: "GET",
url: "https://myjirasite.com/jira/rest/api/2/project/ON/versions?",
dataType: 'jsonp',
//async: true,
beforeSend: function (xhr) {xhr.setRequestHeader('Authorization', make_base_auth("myusername", "mypassword"));},
success: function (){
//Attempt 1 at outputting the result to an alert.
alert(JSON.parse(data));
getData.data= JSON.parse(data);
}
});
}
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return 'Basic ' + hash;
}
setTimeout(function(){console.log(getData.data);}, 3000); // Fire after 3 seconds to get data.
</script>
I don't think $.ajax actually returns anything - but I could be wrong. Either way, that's not too important, because you shouldn't rely on the results of an ajax call being available immediately. Your alert statement is firing before the Ajax request is finished - it sounds like you know that already.
When leveraging asynchronous calls (ajax), its a best practice to have any logic that relies on the data returned from the call to be done in (or triggered by) a callback (or as #Jack Zelig mentions, promises). This is what success parameter of $.ajax is all about. It will get called once the request completes successfully. You can also define complete and error callbacks - which fire once the request is complete (regardless of status) and once the request fails respectively.
So to summarize, your best option is probably this:
var jqXHR = $.ajax
({
type: "GET",
url: "https://myjirasite/jira/rest/api/2/project/ON/versions?",
dataType: 'jsonp',
success: successHandler
});
function successHandler(data) {
alert(JSON.parse(data));
}
In this way, only once data is received will an alert be shown that will contain the data.
Related
I have two js files i.e. myJs1.js and myJs2.js .
From myJs1.js a method of myJs2.js is called.
I want to return r1 and r2 into results(in myJs1.js)
I have tried this:
I declared r1 and r2 variables before the ajax call and
after the ajax call I added:
return [r1,r2];
But it return r1 and r2 as undefined.
When I researched the issue I came across that adding async: false could work but it has so many issues (like browser freezing). Even so I tried it and still was not able to get the values of r1 and r2.
Note: I am uing AJAX for the first time so bear that in mind.
EDIT: There is an ajax call in Js1 in which on success event the method is called. I want to access the result to call another method in the js1
EDIT:LOOK HERE FOR THE CODE
myJS1:
function method()
{
$.ajax({
type: "GET",
dataType: "json",
url: "http://127.0.0.1:8000/***/***",
success: function(response){
result=methodOfmyJs2(response);
load1(r1); //r1 from result
load2(r2); //r2 from result
}
})
}
myJs2 :
function methodOfmyJs2(data)
{
$.ajax({
type: "GET",
data:SomeData,
dataType: "json",
url: "http://127.0.0.1:8000/***/***",
success: function(response){
r1=anotherMethodFromThisJS1(response);
r2=anotherMethodFromThisJS2(response);
result=[r1,r2]
}
})
}
I need to access the value of r1 and r2 to call load1 and load2 method of myJs1.
Ajax calls are asynchronous by default, meaning ajax call function jQuery.ajax() wont wait for the HTTP response to come back before returning.
To get the data after the HTTP response has arrived we have to provide a callback, that's success function. If you want to get this data inside another function just call that function inside success callback.
Following is the code:
//JS1.
function processResponse(r1, r2) {
// do processing here with r1 and r2
}
//JS2.
function methodOfmyJs2()
{
$.ajax({
type: "GET",
data:somedata,
dataType: "json",
url: "http://127.0.0.1:8000/****/****",
success: function(response){
r1=anotherMethodFromThisJS1(response);
r2=anotherMethodFromThisJS2(response);
//calling the success callback
processResponse(r1, r1);
}
});
}
There's another option if you really want to do it, you can make your Ajax call synchronous like below.
$.ajax({
type: "GET",
url: remote_url,
async: false,//now call is synchronous
success : function (data) {
}
});
Now jQuery.ajax() will wait till HTTP response has arrived, then you can return [r1, r2] from methodOfmyJs2().
However you should avoid making synchronous calls as it will make the JS thread wait freezing the UI.
You could use a callback instead.
[EDIT]
myJS1:
function method () {
$.ajax({
type: "GET",
dataType: "json",
url: "http://127.0.0.1:8000/***/***",
success: function (response) {
methodOfmyJS2(function (r1, r2) {
load1(r1);
load2(r2);
});
}
});
}
myJS2:
methodOfmyJs2 (callback) {
$.ajax({
type: "GET",
data: somedata,
dataType: "json",
url: "http://127.0.0.1:8000/****/****",
success: function (response) {
var r1 = anotherMethodFromThisJS1(response);
var r2 = anotherMethodFromThisJS2(response);
callback(r1, r2);
});
}
$.ajax returns promise, which can be chained with then
function getAjaxOutput() {
request1().then(function(data){
// get data from request 1 and pass to request 2
return request2(data);
})
.then(function(data){
// get data from request2
$('#output').text(JSON.stringify(data));
})
return false;
}
try it
https://jsfiddle.net/je7wf4ww/
and if u want to return plain result from getAjaxOutput - u simply can't (without making request sync of course) - u need to return promise which is a wrapper around ajax call and chain it again with then
Apologies if this is a duplicate question, I've followed some steps from another question which didn't seem to help me. I am trying to retrieve some JSON data, store part of the data into a variable and use that variable in a separate function outside of the AJAX request.
My expected response from the json data is http://localhost:8000/tutorials/retrieve/?page=2 (This response shows if I log the variable inside of the AJAX code) however the actual response I get when I try to log the variable from another function is as follows:
n.Event {originalEvent: MouseEvent, type: "click", timeStamp: 1436727171161, jQuery21304066238570958376: true, toElement: div#loadmore.recentTutorials…}
Here is the current code
var recentFirstPage = '';
function retrieveTutorials(){
$.ajax({
type: "GET",
url: "/tutorials/retrieve",
dataType: "json",
success: function(data){
**some unrelated parsing code here**
//Set the variable to what I need
recentFirstPage = data.next_page_url;
},
error: function() {
alert("An error occurred processing AJAX request.");
}
});
}
$('#main-content-wrap').on('click', '.recentTutorials', function(recentFirstPage){
//Does not return expected result
console.log(recentFirstPage);
});
When I click .recentTutorials I expect the console to log the data from JSON however it doesn't. Can someone help clear up my error(s)?
The reason that it doesn't log the data from JSON s that the call is asynchronous. This means that the function will execute top to bottom without waiting for the call to finish.
One method that's used is to leverage deferred objects which return a promise on completion. You can accept an anonymous function to the invoker function so that it's call back is executed within the scope of the click.
Observe:
function retrieveTutorials(){
return $.ajax({
type: "GET",
url: "/tutorials/retrieve",
dataType: "json"
});
}
$('#main-content-wrap').on('click', '.recentTutorials', function(){
//store our function call as an ajax promise
var promise = retrieveTutorials();
//wait for the ajax to return so we can mutate the data
promise.done(function(data){
//now our data will be properly
recentFirstPage = data.next_page_url;
});
});
It seems to me that you are trying to log the data before the ajax is completed. It`s better to use deferreds . Try this:
function retrieveTutorials(){
return $.ajax({ // will return deferred object
type: "GET",
url: "/tutorials/retrieve",
dataType: "json",
success: function(data){
**some unrelated parsing code here**
//Set the variable to what I need
recentFirstPage = data.next_page_url;
},
error: function() {
alert("An error occurred processing AJAX request.");
}
});
}
$.when( retrieveTutorials() ).done(function ( data ) {
console.log(recentFirstPage);
});
The parameter in your click handler is the last and final nail in your coffin. It's always the jquery event and you shouldn't handle it at all.
You do need to call the retrieveTutorials() function within the handler and you need to pass it a callback function that will be executed on success. So your retrieveTutorials() function will look something like this:
function retrieveTutorials(success){
$.ajax({ type: "GET", url: "/tutorials/retrieve",
dataType: "json",
success: success,
error: function() { alert("An error occurred processing AJAX request.");
} }); }
And your click handler:
$('#main-content-wrap').on('click', '.recentTutorials', function(){
retrieveTutorials(function(data){
console.log(data.next_page_url);
});
});
You can also use all the promise based goodness in the other anwers, but the above would be an idiom you'll see again and again.
I have a for loop in java script :
for(i=1;i<=10;i++){
$.ajax({
type: "GET",
url: "insert_names.php",
success: function (data) {
// some codes
}
});
}
this script send all of ajax request Simultaneously !
But It makes problem for me ...
how can i can prevent continue for loop when ajax is working ?
If you need the requests to be executed in serial instead of parallel, you can do that with a little re-structuring. Don't make the AJAX requests synchronous, just use the response of each request to invoke the next one.
Consider a structure like this:
function sendRequest() {
$.ajax({
type: "GET",
url: "insert_names.php",
success: function (data) {
// some codes
}
});
}
Now the request is wrapped in a function that you can invoke. So invoke it in response to the previous request:
function sendRequest() {
$.ajax({
type: "GET",
url: "insert_names.php",
success: function (data) {
// some codes
sendRequest();
}
});
}
It's starting to look like a standard recursive pattern, so all you need now is a terminating condition. Similar to the original loop, just use an incrementing value:
var i = 1;
function sendRequest() {
$.ajax({
type: "GET",
url: "insert_names.php",
success: function (data) {
// some codes
i++;
if (i <= 10) {
sendRequest();
}
}
});
}
Then just invoke it once to start it:
sendRequest();
Now the request should be invoked 10 times as expected (unless my math is off by one, but that should be easy to correct), each request happening in response to the previous request.
With asynchronous programming, don't try to make it synchronous. Instead, perform actions in response to the callbacks.
so this is my setup: I am calling a .each on a number of elements and after a few checks I send an ajax request with some JSON data and on success I apply the server response as an attribute to each element(it is usually an id). After that I push the id to an array.
The problem is that obviously ajax requests are asynchronous and the function that uses the array of element ids fires before all ajax have had time to finish.
I've tried with .when and .then but the callback function keeps getting fired way ahead of the ajax.
Here is how my code looks( I've removed some unnecessary parts):
var order = [];
function sub(selector){
selector.each(function(){
var out = {
"some":"random",
"stuff":"here"
};
$.ajax({
type: "POST"
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
}
})
})
}
$("#button").click(function(){
$.when(sub($(".test"))).then(function() {
console.log(order);
//i have to run the sub function twice so the order doesn't return undefined
});
});
The problem is that when acts on deferred objects, however sub doesn't return anything so when fires right away. So what you need to do is to collect all the deferred objects returned by the ajax calls and return them:
var order = [];
function sub(selector){
var deferredList = []
selector.each(function(){
var out = {
"some":"random",
"stuff":"here"
};
var deferred = $.ajax({
type: "POST",
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
}
})
deferredList.push(deferred)
})
return deferredList;
}
$("#button").click(function(){
$.when.apply($,sub($(".test"))).then(function() {
console.log(order);
//i have to run the sub function twice so the order doesn't return undefined
});
});
The reason to use apply and not when directly is that when doesn't accept array of objects as a parameter and apply provides us the work-around for this.
The argument to $.when() should be a Deferred, but sub() doesn't return anything. This version returns an array of all the Deferreds returned by $.ajax, and calls $.when with them all as arguments; it will then wait for all of them.
var order = [];
function sub(selector){
return selector.map(function(){
var out = {
"some":"random",
"stuff":"here"
};
return $.ajax({
type: "POST"
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
}
})
})
}
$("#button").click(function(){
$.when.apply(this, sub($(".test"))).then(function() {
console.log(order);
//i have to run the sub function twice so the order doesn't return undefined
});
});
Your approach produces a whole lot of more server requests and will scale terribly. Since you want to wait for all results anyway, a much better solution would be to collect all data and send only one ajax request which returns an array of results for each data object.
Using a deferred object (as seen in other answers) then gives you the ability to use that result in a when statement.
try to use a callback-function in success:
var order = [];
function sub(selector, callback){
selector.each(function(){
var out = {
"some":"random",
"stuff":"here"
};
$.ajax({
type: "POST"
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
callback();
}
})
})
}
$("#button").click(function(){
sub($(".test"), function() { console.log(order) });
});
Add attribute async : false to your $.ajax - call. Then the calls are made in sequence after eachother.
I'm experimenting with MCV using jquery. I'm making a call to an api, which returns data - what I want to do is return the data to a variable rather than call an additioanl function within my model. The following code doesn't do what I wish though (the_data = result). Any ideas how I can achieve this?
function lookForSomething()
{
var the_data = $.ajax({ type: "GET",
url: TheUrl,
dataType: "jsonp",
success: function(result) { return result; }
});
return the_data;
}
Many thanks,
J
If understand you correctly, you want the data returned by TheUrl to be the return value of the lookForSomething.
Technically, you could do this, with the async option:
function lookForSomething()
{
var the_data;
$.ajax({ type: "GET",
url: TheUrl,
dataType: "jsonp",
async : false,
success: function(result) { the_data = result; }
});
return the_data;
}
I strongly urge you not to do this. It's un-Javascript-like and it will lock up the user's browser while it's running. Much better to pass in a callback to the function and invoke it from success.
You are probably looking for deferred objects:
function lookForSomething()
{
var the_data;
$.when(
$.ajax({ type: "GET",
url: TheUrl,
dataType: "jsonp",
success: function(result) { the_data=result; }
});
).done(function() {
return the_data;
}).fail(function() {
return '';
});
}
Keep in mind that this is still asynchronous, so when you make a call for var ddd = lookForSomething();, ddd will not have the value you expect since the call may still be running. The only reason I brought up $.when() is because it seems like you require a lot of dependencies. $.when() allows you to wait for multiple ajax commands.