how to manage the ajax response in Dojo - javascript

Ok, this may be a dumb question, but I can't find a way to solve my problem. I have this function:
function getActivityObj(sysId, date) {
var activityObj = dojo.xhrGet({
url: 'calendar/display-subactivities',
content: {'sysId': sysId, 'date': date},
handleAs: 'json',
load: function(result) {
console.log(result);
},
error: function(){
alert("error");
}
});
var ajaxResponse = activityObj.ioArgs.xhr.response;
return ajaxResponse;
}
The problem is that my ajaxResponse variable is always empty, but if in firebug, the xhr object the response property is not empty.
I will use the ajax response in several places in my code so what am I doing wrong or what would be a better way to call the ajax response? Thank you. (Sorry for my bad english)

I suspect the ajaxResponse variable is empty when you call it because the xhrGet() call is made asynchronously, and the result is not actually available yet when you set ajaxResponse and return it from your function.
By the time you view it in firebug, the XHR response has completed but it just isn't there when your code executes.
xhrGet() returns a dojo.Deferred object. You can use that to add a callback function for when it actually completes:
function getActivityObj(sysId, date) {
var activityObj = dojo.xhrGet({
url: 'calendar/display-subactivities',
content: {'sysId': sysId, 'date': date},
handleAs: 'json',
load: function(result) {
console.log(result);
},
error: function(){
alert("error");
}
});
var ajaxResponse;
// activityObj is a Deferred
activityObj.addCallback(function() {
// Use your deferred response
ajaxResponse = activityObj.ioArgs.xrh.response;
// Now inside this function, do whatever you were going to do
// with the xhr return data that you intended to return from
// the wrapping function.
});
}
I am not certain if there's a good way to wrap the xhrGet() call in a function and attempt to return the response though, since it will always be deferred if called asynchronously.
If it is safe to block further execution until the xhrGet() call has actually returned data, you can call it synchronously. Then your code as you have it will work without a deferred callback. Instead you would typically do whatever work the returned data was intended for in the xhrGet()'s load() function.
var activityObj = dojo.xhrGet({
// Call synchronously
sync: true,
url: 'calendar/display- subactivities',
content: {'sysId': sysId, 'date': date},
// etc...

Related

List of AJAX requests to call later with $.when gets called before time

I'm trying to build a list of ajax requests to be fed into the $.when() method, so I can do something when all requests are finished (like this answer exemplifies: https://stackoverflow.com/a/24050887/1952996 ).
I came up with this code (jsfiddle):
function getUserData(username){
return $.ajax({
url:"/echo/json/",
data:{json: $.toJSON({"username": username}),
delay: 3},
type:"POST",
success:function(response)
{
console.log(response);
}
});}
var userList = ["userA", "userB"];
var userRequests = [];
userList.forEach(function(u){
userRequests.push(getUserData(u));
})
When I run this, I see that the data gets logged in the console. Why is that? I thought the way i'm building the ajax request i'm returning the ajax defered object. And then I try to store this objects in the userRequests. But these should not be being called already. What am I missing?
jQuery.ajax is designed in a way that it makes an AJAX call when called, and returns AJAX deferred object.
Your code is absolutely similar to the following:
function getUserData(username){
var result = $.ajax({
url: "/echo/json/",
data: { json: $.toJSON({"username": username}), delay: 3 },
type: "POST",
success: function(response)
{
console.log(response);
}
});
return result;
}
It clearly shows that a request is made at the moment of function call.
You can now use $.when to wait until all requests are completed.
P.S. By the way, you can replace your forEach:
var userList = ["userA", "userB"];
var userRequests = [];
userList.forEach(function(u){
userRequests.push(getUserData(u));
});
with a shorter version using map:
var userList = ["userA", "userB"];
var userRequests = userList.map(getUserData);

multiple ajax async not in order and need synchronous behavior

Sorry, My first language is not English. I am not sure that if I explain my question properly.
My code is like a main function have two ajax functions (Use ajax function to get foursquare API)
main(){
ajax1();
ajax2();
all other codes
}
the ajax2() function has to get result from ajax1() as input and then return result(actually result was pushed in to global array).
all other codes should be processed after two ajax functions are finished. I tried the asyn: false but it is not working. My html file include newest jquery like this
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js" ></script>
I try the jquery function $.when().done() function and the first ajax works. However, the second ajax() function was in the for loop. The for loop will destroy the mechanism of $.when().done() function:
first ajax: in firstjson function
Second ajax: in transfer function
function firstjson(tmpName,tmpLoc,PhotoJson,foursq){
return $.ajax({
type: 'GET',
url: foursq,
dataType: 'jsonp',
success: function(json) {
for (i = 0; i < 3; i++) {
var resultname = json['response']['venues'][i].name;
var resultlocation = json['response']['venues'][i].location;
var resultlat = resultlocation.lat;
var resultlng = resultlocation.lng;
var tmpmarker = new google.maps.LatLng(resultlat,resultlng)
tmpName.push(resultname);
tmpLoc.push(tmpmarker);
var resultid = json['response']['venues'][i].id;
var tmpPhotoJason = 'https://api.foursquare.com/v2/venues/'+ resultid +'/photos?';
PhotoJson.push(tmpPhotoJason);
}
}
});
}
function transfer(PhotoJson,PhotoURL){
for (i = 0; i < 3; i++) {
return $.ajax({
type: 'GET',
url: PhotoJson[i],
dataType: 'jsonp',
success: function(json) {
resultphoto = json['response']['photos']['items'];
photoprefix = resultphoto[i].prefix;
photopresuffix = resultphoto[i].suffix;
photourl = photoprefix+"150x150" + photopresuffix;
PhotoURL.push(photourl);
}
});
}
}
$.when(firstjson(tmpName,tmpLoc,PhotoJson,foursq)).done(function(){
alert("test1");
$.when(transfer(PhotoJson,PhotoURL).done(function(){
console.log(PhotoURL);
all other codes!!!!
});
});
//PhotoURL is global array
So the first "when" function work properly. alert("test1") work after the firstjson was done. However the for loop inside transfer function will break the when function. How can I fix the problem. Please help me. I will appreciate you can give me any related information. Thanks!!!
This will execute ajax2 after ajax1
function anotherMethod(){
//Here you do all that you want to do after the last $ajax call
}
main(){
firstjson(tmpName,tmpLoc,PhotoJson,foursq)
.then(transfer(PhotoJson,PhotoURL))
.then(anotherMethod);
}
As you are returning a promise from the first with the "return $ajax..."
So you organice your code like this:
in methods with ajax calls you return the call as you are doing now
return $.ajax();
that returns a promise that you chain.
And you put what you want to do in another method so you call it in the last "then".
Non-Blocking Example
You should use non-blocking code. You can turn async off (async: false) but this can easily be done in a non-blocking manor using callback functions.
function main(){
$.ajax({ // First ajax call (ajax1)
url: "first/ajax/url",
type: "GET", // POST or GET
data: {}, // POST or GET data being passed to first URL
success: function(x){ // Callback when request is successfully returned
// x is your returned data
$.ajax({ // Second ajax call (ajax2)
url: "second/ajax/url",
type: "GET", // POST or GET
data: {
thatThing: x
}, // POST or GET data passed to second URL
success: function(y){
// y is your second returned data
// all other codes that use y should be here
}
});
}
})
}
This would be the non-blocking approach, nest your function within "success" callback functions. Nest ajax2 within ajax1's "success" callback to ensure that ajax2 is not executed before ajax1 has returned and nest your "all other codes" inside the "success" callback of ajax2 to ensure they are not executed until ajax2 has returned.
Blocking Example
If you absolutely must (please avoid at all cost) you can disable async which will block all JavaScript code from executing until the ajax has returned. This may cause your browser to temporarily freeze until the ajax request has returned (depending on the browser).
function main(){
var x = ajax1();
var y = ajax2(x);
window["y"] = y; // push to global as you requested but why?
// All other codes that can now use y
}
function ajax1(){
var x;
$.ajax({
url: "first/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {}, // POST or GET data being passed to first URL
success: function(r){x=r}
});
return x;
}
function ajax2(x){
var y;
$.ajax({
url: "second/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {
thatThing: x
}, // POST or GET data being passed to second URL
success: function(r){y=r}
});
return y;
}
Once again I stress, try not to disable async that will cause your code to block and is BAD code. If you absolutely 100% have to for some reason than than it can be done but you should attempt to learn how to write non-blocking code using callbacks as the first example does.
Social Network Example
Now I'll do an example of an ajax call to get an array of your friends IDs, and then a series of ajax calls to get each of your friends profiles. The first ajax will get the list, the second will get their profiles and store then, and then when all profiles have been retrieved some other code can be ran.
For this example, the url https://api.site.com/{userID}/friends/ retrieves an Object with a list of friends IDs for a particular user, and https://api.site.com/{userID}/profile/ gets any users profile.
Obviously this is a simplified api as you will probably need to first establish a connection with a apikey and get a token for this connection and the token would likely need to be passed to the api uris but I think it should still illustrate the point.
function getFriends(userID, callback){
$.ajax({
url: "https://api.site.com/"+userID+"/friends/",
success: function(x){
var counter = 0;
var profiles = [];
for(var i=0;i<x.friendIDs.length;i++){
$.ajax({
url: "https://api.site.com/"+x.friendIDs[i]+"/profile/",
success: function(profile){
profiles.push(profile);
counter++;
if(counter == x.friendIDs.length) callback(profiles);
}
});
}
}
});
}
getFreinds("dustinpoissant", function(friends){
// Do stuff with the 'friends' array here
})
This example is "Non-blocking", if this example were done in a "blocking" way then we would ask for 1 friends profile, then wait for its response, then request the next and wait and so on. If we had hundreds of friends you can see how this would take a very long time for all ajax calls to complete. In this example, which is non-blocking, all requests for profiles are made at the same time (within 1ms) and then can all be returned at almost exactly the same time and a counter is used to see if we have gotten responses from all the requests. This is way way way faster than using the blocking method especially if you have lots of friends.

function and defered jquery

Hello i'm very confused on this argument: I know that in javascript function executes in an
asyncronous way sometimes and here is my problem. i have a function called
function createPopupHour()
this function creates an html select element and it doesn't return nothing. I call this function in a $.AJAX request in the success part of the request.
$.ajax({
url:"responseregistrodocente.php",
data:{
operazione:'caricaAssenza',
idAssenza:id_array[3],
codiceFiscale: id_array[0],
data:id_array[1],
tipo:id_array[2]
},
type:"POST",
dataType:"json",
success: function (jsonObject) {
createPopupHourSelect()
//other code
});
},
error: function(error){
//XMLREQQUESTOBJECT
alert(error.responseText);
location.reload();
},
cache:false,
ifModified:false
});
the problem is that when i call the function the other code doesn't attent that my function end. i know that in jquery there is the "deferred Object",maybe i need that my function create a deferred object, and return it to the code. but how is the sintax:? or is there another more easy and dry solution???
is correct something like this?
function createPopupHour select(){ //staff to do
return $.deferred();//it's in pending state
}
and $.ajax
$.ajax({
url:"responseregistrodocente.php",
data:{
operazione:'caricaAssenza',
idAssenza:id_array[3],
codiceFiscale: id_array[0],
data:id_array[1],
tipo:id_array[2]
},
type:"POST",
dataType:"json",
success: function (jsonObject) {
var defered=createPopupHourSelect()
defered.then(function{//other code])
defered.resolve();
});
},
error: function(error){
//XMLREQQUESTOBJECT
alert(error.responseText);
location.reload();
},
cache:false,
ifModified:false
});
Yes, the other code needs to reside in a callback function that will be executed when popup thing is done, just like the popup startup code is executed when the ajax is done. You can either use a primitive callback, or use the more powerful promise pattern.
The syntax for jQuery Deferred objects is
function …() {
var def = $.Deferred();
// start asynchronous task
// when the task is done (in the future), call
def.resolve(…); // optionally with results
// and right now do
return def.promise();
}
Since $.ajax does return a promise as well, you can use chaining via .then (assuming createPopUpHourSelect is in the above pattern):
$.ajax({
url:"responseregistrodocente.php",
data:{…},
type:"POST",
dataType:"json",
cache:false,
ifModified:false
})
.fail(function(error){
alert(error.responseText);
location.reload();
})
.then(createPopupHourSelect) // gets passed the parsed JSON
.then(function(result) { // gets passed the resolve arguments from the popup
// other code
});
If you need the ajax response in the other code as well and don't want to pass it through the popup function, use
.then(function(json) {
return createPopupHourSelect(…)
.then(function(popupResults) {
// other code
});
}) /* returns a promise that resolves with result of other code
.then(…) */

how to use properties and methods withing a JavaScript class to exchange data?

i have small issue with exchanging data in between methods in a JavaScript object (class):
var TEST = (function () {
var TEST = function() {
};
TEST.prototype.get = function() {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
return data; // if i console log this i will get a json obj
}
});
};
TEST.prototype.parse = function(data) {
$.each(this.get(), function(k, v){
console.log(v);
});
};
return TEST;
})();
so i am trying to call one method in the each statement in another method. the issue is that
the response is undefined.
i also tried it like this, but with he same result
var testing = new TEST();
var get = testing.get();
testing.parse(get);
What am i missing? how can i return the data from this.get to be used in this.parse.
thanks
$.ajax() per default is asynchronous. That means, that the execution of your function get() wont wait until the request is finished. Hence you return no value from it, which results in undefined being returned.
In order to have your get() function be able to return a value, you would have to do the request in a synchronous way and set a variable in the outer function (as success itself is just another function, whose return value is not caught):
TEST.prototype.get = function() {
var result;
$.ajax({
type: "GET",
url: "http://test.com/getall",
async: false, // this is the important part!
dataType: "json",
success: function (data) {
result = data;
}
});
return result;
};
EDIT
As mentioned by #pebbl, this will halt the execution of all your scripts, until the request is done. Hence your whole page will be blocked for the time being.
The general approach is to use callbacks in such cases, which will be executed once the requests finished. So in your case something like this:
TEST.prototype.get = function( cb ) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: function (data) {
cb( data );
}
});
};
with later on calling like this:
var testing = new TEST();
testing.get( function( data ) {
testing.parse( data );
});
You can't construct your function this way as you are relying on an asyncronous call, which will return it's result outside of the normal execution flow. The only way you can actually receive the result of your .get function is to use a callback.
Put simply your value isn't being returned from the .get function, it's being returned from the callback you are passing into jQuery's .ajax method.
You'd be far better off redesigning your code so as to still support the asyncronous call -- rather than disabling async.
A rough idea is to change your parse function like so:
TEST.prototype.parse = function(data) {
this.get(function(result){
$.each(result, function(k, v){
console.log(v);
});
});
};
And to change your get function accordingly:
TEST.prototype.get = function(callback) {
$.ajax({
type: "GET",
url: "http://test.com/getall",
dataType: "json",
success: callback
});
};
The above is just a quick example, you'd be wise reading up on the following jQuery topics:
http://api.jquery.com/promise/
http://api.jquery.com/category/deferred-object/
If you design your code around the promise pattern you'll find it complicated at first, but it gives you a lot of power in your code -- and gets around the whole callback stacking madness you can end up with when dealing in ajax calls.
Whilst it's not entirely clear from the jQuery.ajax documentation, this function returns a jqXHR object which implements the promise interface. So this means you can use the promise methods done, always and fail.
http://api.jquery.com/jQuery.ajax/

JQuery .get function vars

Once again having problems being a new to javascript. I want to get the reply from my PHP script using JQuery's get. Here's my function
function getNext(){
var returnData = null;
$.get("get.php", {task:'next'}, function(responseText){
returnData = responseText; }, "text");
return returnData;
}
Now obviously the function returns null even though the request was successful. Why?
Thanks for your help in advance.
Because ajax is asynchronous, it acts independently on its own and so by the time the return statement completes, it hasn't been assigned yet.
function getNext(){
var returnData;
$.ajax({
url: "get.php",
data: {task:'next'},
success: function(responseText) { returnData = responseText },
async: false;
});
return returnData;
}
Note that this may "freeze" the UI because Javascript is single threaded -- it will wait until it receives the response from the server.
You may want to refactor it so that the action is called in the success callback. Could you show us what triggers the invokation of the getNext method?
try this
function getNext(){
var returnData = null;
$.get("get.php", {task:'next'},
function(responseText){
returnData = responseText;
alert('Data ' + responseText);
});
}
You will have to poll whether returnData contains actual data that you want periodically (or put your code into the callback method)

Categories

Resources