Angular js combines asynchronous and synchronous code
I am using angular module resource
to work with my restfull webserver. For example, I have a method that returns an array of 10 elements, and what I want to do is just store the result in some javascript variable ( not in angular scope ) called books
.
So, I wrote a simple method that looks like this:
function getBooks(user_id) {
var books = [];
BookFactory.getBooks.query({ id: user_id }).$promise.then(function (result) {
angular.forEach(result, function(i) {
books.push(i);
});
});
return books;
}
Let's assume BookFactory.getBooks.query works as expected and actually returns 10 items. So there is some simple logic inside this function, I just push each item onto the books array .
Also I have a test function to test the function getBooks()
. Here he is:
$scope.testGetBooksMethod = function (user_id) {
var resut = getBooks(user_id);
alert(resut.length);
};
The result in the notification will always be 0. I know that this part of the code:
BookFactory.getBooks.query({ id: user_id }).$promise.then(function (result) {
angular.forEach(result, function(i) {
books.push(i);
});
});
works asynchronously and while the server request is not being processed, the function getBooks()
returns an empty array of books (please correct me if I'm wrong).
Here is the question, how can I edit my function to work correctly. I want to get data from rest, fill an array with books
this data and then return it.
Thanks in advance.
source to share
Here you need to use the concept of promise, testGetBooksMethod
the controller function will wait until getBooks
the service method completes its call. To do this, you need to return a promise BookFactory.getBooks.query
from the function getBooks
. After receiving the data, books will be created and will be returned from the method getBooks
. When calling the method, getBooks
you need to use a function .then
that will continue to work with chaining promises, when data is returned from getBooks
, then the function will receive the data returned from your service.
function getBooks(user_id) {
var books = [];
return BookFactory.getBooks.query({ id: user_id }).$promise.then(function (result) {
angular.forEach(result, function(i) {
books.push(i);
});
return books;
});
}
controller
$scope.testGetBooksMethod = function (user_id) {
getBooks(user_id).then(function(resut){
alert(resut.length);
});
};
source to share
I want to get data from rest, fill books of arrays with this data and then return it.
That's what. Asynchronous programming is actually incompatible with synchronous programming. Therefore, you cannot simply combine them. You can work in sync, however, and this is where promises get very powerful. You don't return data
, instead you return the state of the Promise object .
So instead of returning, books
return the promise for these books:
function getBooks(user_id) {
return BookFactory.getBooks.query({ id: user_id }).$promise;
}
Then, in the consuming code, you should use this wrapper object with a basic stateful mechanism that will take effect when the books are loaded and available:
$scope.testGetBooksMethod = function (user_id) {
getBooks(user_id).then(function(books) {
alert(books.length);
});
};
source to share