JavaScript: wait for every asynchronous call finished [duplicate] - javascript

This question already has answers here:
$q promise with Underscore _each
(3 answers)
Closed 8 years ago.
I'm trying to load data from multiple sources and want to continue processing only after all data being loaded. Here is my code:
var tables = [];
$http
.get('/tables')
.then(function (response) {
_.each(response.data, function (table) {
tables.push(table);
});
})
// get detail data
.then(function () {
_.each(tables, function (table) {
$http.get('/tables/' + table)
.success(function (data) {
process(data);
});
});
})
.then(function () {
// after everything loaded
// run this function
});
Thanks for your help!

You should use the following:
.then(function () {
return $q.all(_.map(tables, function (table) {
return $http.get('/tables/' + table)
.success(process);
});
})
Unrelated to the main part of your question, but note that you don't need to define an all new anonymous function for .success if you're just going to pass the parameter into process().
See also: $q promise with Underscore _each

Related

Array returns empty before getting fullfilled [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 1 year ago.
i'm implementing Toast Ui Calendar in my php/js app and in the flow of javascript execution the program encounter this function:
function setSchedules() {
cal.clear();
generateSchedule();
cal.createSchedules(ScheduleList);
refreshScheduleVisibility();
}
When i refresh the page to visualize the events retrived from db via axios and php function, the calendar is empty, then if a select month view or go back one week and come back to the current week the events are rendered.
The problem seam to reside in the function generateScedule() which is declared inside a schedules.js file and that declare and fulfill the ScheduleList array to pass to the createSchedules function, follow the code:
var ScheduleList = [];
function generateSchedule() {
axios({
method: 'post',
url: 'path-to-data',
})
.then(function (response) {
ScheduleList = [];
let data = response.data;
for(let key in data){
ScheduleList.push(data[key]);
};
})
.catch(function (error) {
console.log(error);
});
return ScheduleList; //with or without this return the result doesn't change
}
It's like if the array ScheduleList at first is returned empty (whithout waiting) while the function is still fulfilling it, console.log inside varoius parts of the function confirm it.
If i fulfill the array manually with pasted json data, everything is returned immediately an fine.
I know it has probably to do with javascript stacks etc..
Any help would be appreciated.
Thanks a lot in advance!
Because axios is async so the ShceduleList stay empty,
the return is executed before the loop of data.
Try this :
function generateSchedule() {
return axios({
method: 'post',
url: 'path-to-data',
})
.then(function (response) {
var ScheduleList = [];
let data = response.data;
for (let key in data) {
ScheduleList.push(data[key]);
};
return ScheduleList;
})
.catch(function (error) {
console.log(error);
});
}

AngularJS HTTP use response [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
Hello this is my second time using AngularJS... I create a http request and no problem with it.
But the question is, how i can get the result of this request or put in a variable ?
var cust_url = "RETURN A JSON";
var FINAL_FILE = "";
$http.get(cust_url)
.then(function (response) {
$scope.details = response.data;
//--> do multiple modify to response.data
FINAL_FILE = 'something';
});
$scope.data = {
/*USE HERE --> FINAL_FILE
return -> undefined on console if i try to access to FINAL_FILE
*/
};
Like the example... sorry i think is a stupid error. Thanks for your time.
$http request is asynchronous, this is the reason that you get the undefined value. If you want to use the response data, you have to do it inside the then callback, where the data are available, like this:
$http.get(cust_url)
.then(function (response) {
$scope.details = response.data;
//--> do multiple modify to response.data
FINAL_FILE = 'something';
// here use the $scope.details or call a function to use data
$scope.data = { };
});
Return data to the .then method and save the promise:
var finalFilePromise = $http.get(cust_url)
.then(function (response) {
$scope.details = response.data;
//--> do multiple modify to response.data
FINAL_FILE = 'something';
return FINAL_FILE;
});
To use, extract the data from the promise:
$scope.data = {
//USE HERE --> FINAL_FILE
finalFilePromise.then(function(FINAL_FILE) {
console.log(FINAL_FILE);
});
};
For more information, see
AngularJS $q Service API Reference - Chaining Promises

How to get data from function to variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
How to make a function wait until a callback has been called using node.js
(11 answers)
Closed 5 years ago.
I'm learning node.js and I have a problem. How to get data from function to variable?
function loadOrInitializeTaskArray(file, cb) {
fs.exists(file, function(exists) {
var tasks = [];
if (exists) {
fs.readFile(file, 'utf8', function(err, data) {
if (err) throw err;
var data = data.toString();
var tasks = JSON.parse(data || '[]');
cb(tasks);
})
} else {
cb([]);
}
})
}
function listTasks(file) {
loadOrInitializeTaskArray(file, function(tasks) {
for (var i in tasks) {
console.log(tasks[i]);
}
})
}
Function listTasks works correctly, but I would like create own function, for example customListTasks:
function customListTasks(file) {
var list = loadOrInitializeTaskArray(file, function(){});
console.log(list);
}
This not return me errors, but console.log on list return me "undefined". How can I get this data to variable list?
Short answer: you can not.
Because the loading in loadOrInitializeTaskArray is asynchronous, all the magic has to happen in the callback that you are passing. You cannot just 'return' a value from it.
Option 1: Place all logic that depends on the loaded data in the anonymous function that you pass as callback.
var list = loadOrInitializeTaskArray(file, function(tasks){
console.log(tasks);
});
Option 2: Use Promises. They work essentially like callbacks, but are slightly more flexible and make chaining easier.

Assigning values to an array in an async method [duplicate]

This question already has answers here:
How to use promise with two http requests
(3 answers)
Closed 7 years ago.
(Note: This is AngularJs but should be a "standard" Javascript-Issue)
I use the following method to read the content of a json-file inside an angular controller:
$http.post(apiUrl + 'data.php?select', {directory: "customers", file: "john"})
.success(function (data) {
$scope.customers= data;
})
(The php - function simply returns a (valid) JSon-Array).
This works as expected; The content is stored inside $scope.customers
Because this kind of actions is needed in different places I decided to write a service for this:
myApp.factory('util', function ($http) {
return {
getFile:function(directory, file, target) {
$http.post(apiUrl + 'data.php?select', {directory: directory, file: file})
.success(function (data) {
target = data;
});
}
};
And then call this method the follwing way:
util.getFile("customers","john",$scope.customers);
But this does not work ($scope.customers remains empty).
After digging into SO I understand that this cannot work this way, because arrays are not passed by-reference but by-value.
But is there another way to achieve what I want to do?
I think the problem is that target is now a local variable because javascript is always pass by value, so in this case target refers to the same object like $scope.customers. But overwriting target will not overwrite $scope.customers, then target will just point to another object.
You should set the variable using .then(result) like this:
myApp.factory('util', function ($http) {
return {
getFile:function(directory, file, target) {
return $http.post(apiUrl + 'data.php?select', {directory: directory, file: file})
}
};
and call it with
util.getFile("customers","john").then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.customers = response.data;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log("Error getting customers")
});
This also makes it clear that util.getFile is an asynchronous function and you can place code here that gets executed when the result is available.
Note: Another alternative to stay with you approach would be to overwrite a property of the object (but I prefer the approach above):
myApp.factory('util', function ($http) {
return {
getFile:function(directory, file, target) {
$http.post(apiUrl + 'data.php?select', {directory: directory, file: file})
.success(function (result) {
target.data = result.data;
});
}
};

Javascript - Pass callback value to calling variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have a function and a variable....
var imageURLs = retrieveRemoteImages(vinUrls)
if imageURLs !== undefined) {
// do something
}
function retrieveRemoteImages(urls) {
var imageURls = [];
processSpinnerActivity(START_IMAGES_IMPORT);
importImagesforSlideShow(REMOTE_IMAGES_URL, urls, function (images) {
if (images !== undefined) {
imageURls = images;
return imageURls;
}
})
return imageURls;
}
This does as intended ....
function importImagesforSlideShow(imagePath, urls, call_back) {
var functionName = 'importImagesforSlideShow'
$.ajax({
type: "POST",
url: LOCAL_PROCESSING_MODULE,
data: {data: [imagePath, urls, IMAGE_EXTENSION_QUALIFIER], functionid: functionName},
dataType:"json",
success: function (res) {
processSpinnerActivity(IMPORT_IMAGES_SUCCESS);
call_back(res);
},
error: function (err) {
processSpinnerActivity(IMPORT_IMAGES_ERROR);
console.log(err.message);
}
});
}
The callback works fine, but I am not able to pass the eventual value to imageURLs and I need to, as the next step cannot occur until it has a value.
Any ideas?
Thanks!
This is not a duplicate question, I have no issues with my AJAX returning the async value*
It's not possible like that, you are executing a piece of async code. So your code keeps running while their isn't any data yet. You have to process your data in a callback, for example like this:
function retrieveRemoteImages(urls, callback) {
processSpinnerActivity(START_IMAGES_IMPORT);
importImagesforSlideShow(REMOTE_IMAGES_URL, urls, callback);
}
retrieveRemoteImages(vinUrls, function(imageURLS) {
//do your stuff
});

Categories