Optional first promise in Angular chain - angularjs

I have 2 $http calls that return promises but the first one is optional. I believe that I have to first create a promise using $q.defer() but I am missing something.
Here's my non working attempt:
var p = $q.defer();
if (condition) {
p = p.then(doOptionalFirst());
}
return p.then(doOther());
What is correct syntax to chain these 2 calls with the first being optional?

Use $q.when (or $q.resolve with AngularJS 1.4.1) to create an already resolved promise.
var p = $q.resolve();
if (condition) {
p = p.then(doOptionalFirst);
}
return p.then(doOther);
If you are using a deferred, you have to chain to the .promise and then resolve the deferred at an appropriate time. In this case you can consider that if condition is true the deferred is automatically resolved. Thus you can skip some extra possibly confusing code by just using an already resolved promise.

Related

Difference between Sequential and Parallel executing in $q

In both of at the time of execution of an asynchronic operation only.
But how the $q handle for this is a Sequential call or Parallel call on runtime?
and let me brief explanation about the Difference between Sequential and Parallel executing in angular $q
Parallel Execution is something in which it doesn't wait for the previous process to be done,and Sequential is something in which process are executed one after another.
$q service is used for asynchronous call (parallel execution | promise handling),by default it does parallel execution,it does not have support for sequential execution.
If you want a sequential execution you have to handle it manually, wheich means after getting response from one call you make another call.
var promise;
promise.then(fun(){
var promise;
promise.then(fun(){
})
})
To execute promises in parallel:
var promise1 = promiseAPI(params1);
var promise2 = promiseAPI(params2);
var promise1and2 = $q.all([promise1, promise2]);
To execute promises sequentually, return the next promise to the first promise success handler:
var promise1 = promiseAPI(params1);
var promise1then2 = promise1.then(function() {
var promise2 = promiseAPI(params2);
//return to chain
return promise2;
});
Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain.
-- AngularJS $q Service API Reference -- Chaining Promises.

$q.defer() creating a resolved promise

looking for some help on an issue that makes me losing my hair ! :)
I have to send a series of call to an API I consume. so I have created a factory with a function like
addItem : function(){
var deferred=$q.defer();
//call to the API
.then(function(response){
deferred.resolve(process(response.data));
}, function(response){
deferred.reject(errorManagement(response.status));
});
}
return deferred.promise;
}
Then I have built an array with code:
for(var i=0; i<nbOfElements; i++) {
arrayOfPromises[i]=Factory.addItem();
}
$q.all(arrayOfPromises).then(..)
My expectation is that the $q.all will resolve only when all calls to the API have been completed.
Unfortunately, it appears that this is not the case, and then I display a partial result, not satisfactory
after some debugging, it appears that the promises returned by the factory all have $$state.status = 1, which seems to be "resolved" state, explaining why the $q.all resolved before I would like.
(link to the values of $$state.status)
Still I find this weird as I have used this $q.defer() a lot, but without $q.all and it always worked fine
Any explaination on this issue and how to solve it would be much welcome :)
Simply return the $http.get() promise will actually work: JSFiddle.
If you want to do some pre-processing in the factory before returning the data (like your process and errorManagement), check demo: JSFiddle.
The $q.all callback function not invoked only after all promises are resolved. It is not because of $q.all.
Your array code has problem: arrayOfPromises[i]=Factory.addItem();. You'd better use push to expand the array.
Maybe I can't solve your problem, just giving suggestions:
You can save a lot of code by returning the promise of your API call instead of creating new promises (this is one of the promise anti-patterns)
addItem: function() {
//call to the API
return $http(something).then(function(response){
return process(response.data);
// if you happen need to reject here, use $q.reject(reason/data);
}, function(response){
return $q.reject(errorManagement(response.status));
});
}
I'm more comfortable on assigning into an array using push
var arrayOfPromises = [];
for(var i=0; i<nbOfElements; i++) {
arrayOfPromises.push(Factory.addItem());
}
$q.all(arrayOfPromises).then(..)
You are not missing the part before .then in the addItem function in your real code, are you?

asynchronous calls inside for loop angularJs

I'm trying to make a call to a function 'submittoServer' which is inside factory 'pService', which makes $http call and then broadcast the data. The call to the 'submittoserver' is happening inside a for loop. Problem here is that I couldn't see the actual call is being made until the last loop, which is sending only the last item, but as you see in the code below I want to update one particular variable after every call, can someone please suggest how can I don't that. I can't do call back here as I've other method that call this same factory function with different inputs.
for (var i = vr.lines.length - 1; i >= 0; i--) {
if (parseInt(vr.lines[i].id) === id && Boolean(vr.lines[i].IsVoided) != true) {
lineId = vr.lines[i].lineID;
pService.submitToServer(actionId, { "IData": id }, ineId)
linesRemoved = linesRemoved + 1;
}
if (linesRemoved === lineqty)
{
updateModel = true;
}
}
The problem here is that your service is a promise to return data. Your function will keep looping and running before the promise is resolved. You need to refactor your loop to take this into account.
Either add a .then(fn(){}) to handle the resolve promise. Gather up all the changed lineIds and submit them all at once and (again) handle the resolved promise with a .then(fn(){}). Lastly, given you next set of code logic, you probably want to do something more like $q.all to wait on all promise(s) to resolve before moving forward (see Wait for all promises to resolve)
Example
before your for loop:
var self=this;
self.linesRemoved = 0; // or init as needed.
Inside your for loop.
pService.submitToServer(actionId,{data}).then(function(resp){
self.linesRemoved++; // shortcut, this does +1 to itself.
});
Why do you have update model? With Angular your data is two-way bound and should just react to it being changed.
Sample $http call with return in a service, this is a promise itself:
return $http.post(url, data, { cache: true });
Use this in a controller like
service.callHttp(data).success(function(resp){
self.linesRemoved++;
}).error(function(resp){});
If you have to wait it might be better to hold all and wait until they are all finished.
var promises =[];
for(){
promises.push(service.callHttp());
}
$q.all(promises).then(function(){
// do work if(self.linesRemoved==lineQty)
// update... You can't evaluate until they are all finished right?
});

Break Out of then promises in Angularjs

I am trying to find a way to break out of a promise chain in AngularJS code. The obvious way was to return an object and then check is validity in every "then" function in the chain.
I would like to find a more elegant way of breaking out of a then chain.
In angular, there is the $q service that can be injected in directives, controllers etc, that is a close implentation of Kris Kowal's Q.
So inside of then function instead of returning a value or something else that would be chained to the next "thenable" function, just return a $q.reject('reject reason');
Example:
angular.module('myQmodule',[])
.controller('exController',['$q',function($q){
//here we suppose that we have a promise-like function promiseFunction()
promiseFunction().then(function(result1){
//do the check we want in order to end chain
if (endChainCheck) {
return $q.reject('give a reason');
}
return;
})
.then(function(){
//this will never be entered if we return the rejected $q
})
.catch(function(error){
//this will be entered if we returned the rejected $q with error = 'give a reason'
});
}]);

What $q.defer() really does?

I'm learning about Angular JS and on the moment I'm trying to understand about promises and async programming and I have this doubt about $q.defer(). My point is the following: usually when people work with promises they do something like that, considering that $q is already available
function someAsyncFunction() {
var deferred = $q.defer();
/* Do things and if everything goes fine return deferred.resolve(result)
otherwise returns deferred.reject()
*/
return deferred.promise;
}
What is this really doing? When we do var deferred = $q.defer() it imediately switches all the execution of that function to another thread and return the promise being a reference to the results of this operation that is still performing there?
Is this the way we should think about when creating async methods?
With $q u run functions asynchronously.
Deferred objects signals that something, some task is done.
var defer = $q.defer(); // we create deferred object, which will finish later.
defer.promise // we get access to result of the deferred task
.then( // .then() calls success or error callback
function(param) {
alert("i something promised " + param);
return "something";
}); // u can use 1 or more .then calls in row
defer.resolve("call"); //returns promise
Here example:
http://jsfiddle.net/nalyvajko/HB7LU/29048/
Angular's $q service is based on the Javascript library Q. You can read more about it in the Q documentation, or read the code in the github repo. I think this part snipped from the introduction to the documentation explains it best:
If a function cannot return a value or throw an exception without
blocking, it can return a promise instead. A promise is an object that
represents the return value or the thrown exception that the function
may eventually provide. A promise can also be used as a proxy for a
remote object to overcome latency.

Resources