undefined variable after ajax request [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I'm using jQuery. I have a function that fetches data from a remote server called "get_cats". I call it to fill an array with the values returned. When AJAX is completed I want to return the values.
But It doesn't work, the value returned is undefined. This is pretty basic but I can't see where It fails. Does anyone has a clue ?
$(function () {
var url = "http://someurl.com/service/";
var cats = [];
cats = get_cats(url);
function get_cats(url) {
var categories = [];
$.getJSON(url + "cats", function (data) {
$.each(data, function (i) {
categories.push(data[i].name);
});
return categories;
});
}
$(document).ajaxStop(function () {
console.log(cats); // fails and returns undefined :'(
});
});

Oh no AJAX is asynchronous, you cannot return anything from it. You should consume the results of an AJAX request only inside the success callback:
$(function () {
var url = "http://someurl.com/service/";
get_cats(url);
function get_cats(url) {
var categories = [];
$.getJSON(url + "cats", function (data) {
$.each(data, function (i) {
categories.push(data[i].name);
});
// Only here you can consume the results of the AJAX request
// Do not attempt to return them, it doesn't make any sense
console.log(categories);
});
}
});

You can try:
$.ajaxSetup({async:false});
before AJAX call.
But it will stop browser while respone will be returned.

Related

JQuery.when() isn't waiting for a function return [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I have the following code structure :
var firstPagePromise = $.ajax('url1').then(function (data) {
//do stuff
});
var secondPagePromise = $.ajax('url2').then(function (data) {
//do stuff
});
$.when(firstPagePromise, secondPagePromise).done(function () {
// do stuff
});
I want to execute some code after doing two request using JQuery.when()
. Written like this, it's working, but I would like to put the two requests in functions for easier maintenance of the code and I'm unsure how to do that.
function fetchFirstPage() {
var firstPagePromise = $.ajax('url1').then(function (data) {
//do stuff
});
return firstPagePromise;
}
var firstPagePromise = fetchFirstPage();
// same for the second page ...
$.when(firstPagePromise, secondPagePromise).done(function () {
// do stuff
});
this does not work and seems to fire when() without waiting for the execution of the two functions, is there any way I could execute the code in the when function only if the two previous function have ended ?
The following code shows my issue on a minimal example, I'd like to get the variable title to print in the console after the call to when but I get "undefined" instead. I think that I understand what's going on, inside the function fetchPage(), title is returned before the request finishes. I think that a callback function could resolve the issue, however, is there any other way ?
function fetchPage() { //fetch the random start page
var title;
var pagePromise = $.ajax('https://en.wikipedia.org/w/api.php?action=query&origin=*&format=json&list=random&continue=-||&rnnamespace=0&rnlimit=1').then(function (data) {
title = data.query.random[0].title;
console.log("in request : " + title);
});
console.log("in function return : " + title);
return [title,pagePromise];
}
var firstPageResult = fetchPage();
var title = firstPageResult[0];
var pagePromise = firstPageResult[1];
$.when(pagePromise).done(function() {
console.log("in when : " + title);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>

Ajax Jquery: how return result? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
In script-a.js I have this function:
function callGetAjax(url,callback) {
$.get(url, {}, function(result) {
// this will call the callback and pass the result
callback(result);
});
}
In script-b.js I call it:
var url = '/feed/location';
callGetAjax(url,function(result)
{
//console.log(result); <= of course this logs right
data = result;
return data;
});
console.log(result); // <= ReferenceError: result is not defined
console.log(data); // <= ReferenceError: data is not defined
I don't want make async:false but I need to "export" data to elaborate it. Thank you.
Ajax is an async tool so you can use data only inside it. So, if you need to alter the dom with data you should do it directly:
var url = '/feed/location';
callGetAjax(url,function(result)
{
//console.log(result); <= of course this logs right
data = result;
$('#some_dome_item').html(data);
});

Return a nested function from inside a node module [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 8 years ago.
I trigger a function using require() in my app.js file and the result returned is 'undefined'. I think this is due to the function being nested. What is the best way to return the nested value. I have tried the method below but the function appears to be asynchronous and the returned value is returned as undefined before the data is provided.
app sample code --
app.get("/twitter/:handle", function (req, res) {
var handle = req.params.handle;
var twitter = require('./module/twitter');
var data = twitter.searchHandle(handle);
console.log(data);
res.sendStatus(data);
});
module sample code -
var twitter = {
searchHandle: function(handle){
var dataToReturn;
T.get('search/tweets', { q: handle, count: 100 }, function(err, data, response) {
dataToReturn = data;
});
return(dataToReturn);
}
};
module.exports = twitter;
searchHandle is an async call. Returning dataToReturn will always be undefined as it's value has not yet been populated. You will need to pass a callback function to searchHandle to be executed once dataToReturn is populated.
//app.js
var handle = req.params.handle;
var twitter = require('./module/twitter');
var data = twitter.searchHandle(handle, function (data) {
console.log(data);
res.sendStatus(data);
});
//twitter.js
var twitter = {
searchHandle: function(handle, callback){
T.get('search/tweets', { q: handle, count: 100 }, function(err, data, response) {
callback(data);
});
}
};
module.exports = twitter;

Replace synchronous AJAX logic with asynchronous logic [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I was having an obsolete JS library which was making API call Synchronous for which I decided to write JS function which can make them Async using jQuery.
In the following code the getData function is to be a generic function which makes API calls according to params passed and then extract data from the received XML/JS.
The second call(getAllData2) needs values from the result set of getData so I need a callback kind of thing in which the subsequent call can be made after the data is available from the 1st call.
Can this be achieved without the ajax success call back as I want getData function to remain generic.
I had tried jQuery promises but that gives me the raw data of the call instead of the processed one which I will have to process in each of the done callback separtely.
getData(param1,param2..){
var retData = {};
......Param dependent code here..
jQuery.ajax({
url:....,
.......
success: function(resp){
if(resp.length > 0){
jQuery.each(resp,function(key,val){
var i = 0;
var retObj = {};
jQuery.each(val,function(k,v){
retObj[k] = v;
i++;
});
retData[key] = retObj;
});
}
---Process recieved XML/JS and Insert values in retData here--
}
});
return retData;
}
var getAllData = getData(x,y);
var getAllData2 = getData(a,b); // this call needs param from getAllData.
Please suggest.
Thanks
Promises are indeed what you should be using.
That will allow you to structure your logic like this:
function processResult(resp) {
var retData = {};
if(resp.length > 0){
jQuery.each(resp,function(key,val){
var retObj = {};
jQuery.each(val,function(k,v){
retObj[k] = v;
});
retData[key] = retObj;
});
}
return retData;
}
getData(x, y)
.then(function (result) {
var processed = processResult(result);
return getData(processed);
})
.then(function (result) { // result is the result of the second getData()
// use result
});
If you want to do pre-processing of the results in your getData() function, again you can do this with promises:
function getData(param1,param2..) {
......Param dependent code here..
return $.ajax({
url:....,
.......
})
.then(function (resp) {
var retData = {};
if(resp.length > 0){
$.each(resp,function(key,val){
var retObj = {};
$.each(val,function(k,v){
retObj[k] = v;
});
retData[key] = retObj;
});
}
return retData;
});
}
getData(x, y)
.then(function (processedResult) {
return getData(processedResult, otherParameter);
})
.then(function (processedResult2) {
// use processedResult2
});

How to return a function from a deferred object [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I have a function which is passed a list of URLs (in this case a list of json files) that makes asynchronous ajax calls for each resource, and once they are done returns a single object with the contents.
function loadModels(modelList){
var modelObject = {}
for(model in modelList){
var urlPath = modelList[model].indexOf(".json") > -1 ? 'model/'+modelList[model]+'json' : 'model/'+modelList[model]+'.json';
$.ajax(urlPath).done(function(jsonData){
modelObject[modelList[model]] = jsonData;
});
}
console.log(modelObject);
return modelObject;
}
Trouble is, the console always logs Object{} since the function returns before the deferred objects resolve. If I set async: false then it works just fine, but I don't want the requests to wait for each other.
How can I force the function to wait before returning and still make calls asynchronously?
EDIT: The deferred solution in the link isn't a complete enough answer. The issue I was running into was related to closures. Here's the working code block:
function loadModels(modelList, callback){
var promises = [];
for(model in modelList){
(function(){
var currentModel = modelList[model];
var urlPath = currentModel.indexOf(".json") > -1 ? 'model/'+currentModel+'json' : 'model/'+currentModel+'.json';
var promise = $.ajax(urlPath);
log('pulling model: ' + currentModel);
promise.done(function(jsonData){
modelObject[currentModel] = jsonData;
log('model pulled: ' + currentModel);
});
promises.push(promise);
})();
}
$.when.apply(null, promises).done(function() {
callback(modelObject);
});
}
You can use jQuery.when() to wait for all the promises to resolve before continuing...
var promises = [];
for(model in modelList){
var urlPath = modelList[model].indexOf(".json") > -1 ? 'model/'+modelList[model]+'json' : 'model/'+modelList[model]+'.json';
var promise = $.ajax(urlPath);
promises.push(promise);
promise.done(function(jsonData){
modelObject[modelList[model]] = jsonData;
});
}
$.when.apply(null, promises).done(function() {
console.log(modelObject);
});
when the last ajax-done event is finished trigger an event and pass your object to the event data
and where you need the data handle that event.
$.event.trigger({
type: "afterMyAjaxDone",
data: MyDataObject
});
$(document).on('afterMyAjaxDone', function (e) {
var MyDataObject = e.data;
}

Categories

Resources