Resolving the resolved promise again - angularjs

I'm using $q of AngularJS, when I create a single promise and that promise is already resolved, can it be resolved again? I don't know if this is possible but if not is there a way that I can resolve the same promise again and again. I was thinking of using the notify way but I don't know if there are other ways to do this.

From Mastering Web Application Development with Angularjs, by Kozlowski and Bacon, Chapter 3 "Communicating with a Back-end Server", section "The Promise API with $q":
A promise that was resolved or rejected once can't change its state.
There is only one chance of providing promised results. In other words it is not possible to:
Resolve a rejected promise
Resolve an already resolved promise with a different result
Reject a resolved promise
Reject a rejected promise with a different rejection reason
Those rules are rather intuitive.
For example, it wouldn't make much sense if we could be called back with the information that there are problems with a pizza order delivery after a pizza was successfully delivered (and probably eaten!).
If you provide more code and we can understand better what you are trying to do we might be able to help you.

what I simply did was reinitialize promise again like so:
var appReadyDeferred = $q.defer();
this.prepareAppReadyDeffered = function() {
appReadyDeferred = $q.defer();
};
this.appReady = function() {
return appReadyDeferred.promise;
};
this.appResolve = function() {
appReadyDeferred.resolve();
};
this.appDeferr = function() {
appReadyDeferred.reject();
};
So I can use
someService.appReady().then(function() {
// some code
});
And reinit it using
someService.prepareAppReadyDeffered();
I'm not sure this is the best possible resolution but it seems to work.

Related

What is the right way to chain calls to services in AngularJS?

I need to invoke a Restful service endpoint to get an Id and once I got the result I should invoke a second Restful service endpoint through a angularjs service.
First call returns a customer ID, with this customer ID I need to search for additional info about that customer.
As I should call and and wait for promises I don't think nesting calls to promises is a good pratice. What I mean is that something like the below code isn't supposed to be a neat solution. Am I right or wrong? What should be a good way to achieve this task.
someService.someAction().then( function(data){
var id = data.data;
antoherCallToAnotherService.someOtherAction(id).then(function(data2){
//do some stuff
);
);
Thank you
This is quite typical approach. However, you can optimise it by chaining multiple promises:
someService.someAction().then(function(response) {
var id = response.data;
return antoherCallToAnotherService.someOtherAction(id);
})
.then(function(data2) {
// data is available
});
This is not that bad at all, however can be improved even more if you want. You should probably not make the first promise resolve with entire response object, underlying service should resolve with actual (maybe processed data). Then your code could become:
someService.someAction()
.then(antoherCallToAnotherService.someOtherAction)
.then(function(data) {
// data is available
});
For above to work, someService.someAction should resolve with response.data (which is an id in your case).

Angular and Meteor flicker on page load

I had an issue with and angular-meteor project flickering every time a state using the campaigns subscription, would load. By flickering, I mean the data was there, then it would go away and come back a half second later.
I added this to the resolve property of the state (using ui-router):
campaigns: ($q) => {
var deferred = $q.defer();
Meteor.subscribe('campaigns', {
onReady: deferred.resolve,
onStop: deferred.reject
});
return deferred.promise;
}
The flickering stopped, but I don't really understand this code. Can someone who understand angular break this resolve/defer situation down?
Just not sure why it worked. thanks.
$q is angular's implementation of promises.
in a very itty bitty nutshell, a promise has two callbacks that resolve when data is returned; a resolve function if the call succeeds and a reject if the call fails. whatever data it gets will be passed into these functions (essentially doing deferred.resolve(data) or deferred.reject(error)) . $q.defer() allows us to assign the resolution/rejections later.
meteor's subscribe function takes a few arguments. the string name of the collection, a function that returns an array of arguments to be passed to the collection, and an object/function. the object part of the final argument expects an "onReady" and "onStop" functions, and will execute those functions and pass along any data it gets. we pass in our callbacks here.
finally, we return the promise. resolve.campaigns will be a promise, which we can get the values from using the .then(successCallback, failureCallback) call. meteor handles this behind the scenes.

Pattern for returning data from Angular AJAX calls

Take a look at this method returned in a factory:
fetchEmployeeList: function() {
var q = $q.defer();
$http.get('/Employee/')
.success(q.resolve)
.error(ajaxErrorHandler.handleError);
return q.promise;
}
The author of this code says that this is the model we should use for returning data from HTTP endpoints. Basically, any time we need data from a service, we should use this pattern. The author is under the impression that this is preferred over returning $http.get()'s return value instead.
I don't understand the point of this code, though. I thought $http.get() does return a promise.
Can someone explain what this example snippet is doing or what they think the author might be trying to do?
That's the deferred anti-pattern, which practically warps a promise when not needed.
in your case returning a q.promise seems like an abuse since the HTTP object can return a promise itself.
I'd refactor the code to the following:
fetchEmployeeList: function() {
return $http.get('/Employee/');
}
you can take a look to this blog post for more reference as well,
don't be afraid to open a discussion with whoever is suggesting that approach.

Track progress of facebook graph api requests

I am willing to track the progress of the querying from Facebook's graph api. I have this promise in an angular service
getPosts: function() {
var deferred = $q.defer();
FB.api(
"/me/home", {since:'yesterday','limit': limit},
function ( response ) {
if ( response && !response.error ) {
deferred.resolve(response);
}
}
);
return deferred.promise;
},
and in my controller I use FBS.getPosts().then(function (data) {...}); . I am willing to be able to keep track of the progress of this promise and be able to display it on my page. Any ideas if this is even possible? I tried adding function (progress) , after the error function of the promise in my controller, had no luck though. Somewhere I read you can use .progress(function (progress){...}) like the .then one but it didn't work.
I don't like leaving questions in the promise tag open as I've made is a personal goal to keep it clean :) so here goes:
Facebook does not expose that functionality, if you want you can track the progress of multiple requests (that is, how many out of N requests are done) but that's not the same thing.
What you are asking for is simply put - impossible. There is no way to know how far the query has progressed without Facebook telling you, and they're not telling you.
Happy coding.

AngularJS Download Settings from Servers

We have an endpoint on our API that includes a set of settings (like default text, other endpoints, etc.). Our frontend is written in AngularJS and we're trying to figure out the best way to get them back to the client, and make them available throughout all directives in the application. Right now our best solution is to include settings as a directive:
angular.module('ourapp')
.factory('settings', function ($http) {
var url = 'http://localhost:8080/settings';
return function (callback){
$http.get(url).success(callback);
};
});
But then all the other calls are wrapped asynchronously.
Is there a better way to do this?
Since the settings come asynchronously from the server, their availability will inherently be asynchronous. If your logic depends on the settings being available, then there is probably no better solution than using promises.
angular.module('ourapp').factory('settings', function($http) {
var url = 'http://localhost:8080/settings';
return $http.get(url); // returns a promise
});
You could use $route to resolve the promise before instantiating controllers. The settings would then be synchronously available in the controllers.
You can also simulate promise unwrapping, i.e. immediately (synchronously) returning an object, which later will be filled with real data. This is great for scopes and templates, and was previously a feature of Angular itself. Be aware that the simulated promise unwrapping may cause bugs if not used cautiously, because the settings data may or may not be there.
Example:
angular.module('ourapp').factory('settings', function($http) {
var url = 'http://localhost:8080/settings';
var settings = {};
$http.get(url).success(function(data) {
angular.extend(settings, data); // fills in data from server
});
return settings; // immediately (synchronously) returned
});

Resources