This question already has answers here:
AngularJS : $q -> deferred API order of things (lifecycle) AND who invokes digest?
(2 answers)
Closed 6 years ago.
I have a very simple function in a jasmine test where I am simply returning $q.reject
var mockFunction = function() {
return $q.reject("error");
};
which I call:
mockFunction().catch(function(){
// ... blah
});
the catch callback function is never being invoked. If I understand correctly $q.resolve should create a promise, rejected immediately and return the rejected promise so I'm not sure why this is not working
Any insights are appreciated. Thanks!
$q promise chains aren't executed automatically in specs, it should be
mockFunction().catch(function(){
// ... blah
});
$rootScope.$digest();
to launch it, the chain will be executed synchronously in this case.
Related
This question already has answers here:
Why is the method executed immediately when I use setTimeout?
(8 answers)
Closed 6 years ago.
Why when a promise chain has an error it will not execute .then unless the .then references an external method with a parameter?
So this example I purposely throw an error in the promise chain. The first three .then's do not fire, as expected. However, the last .then that has a method with a parameter, fires. Why? And then the .catch fires, as expected.
var Promise = require('bluebird');
var testVar = 'foo';
errorOnPurpose()
.then(function() {
console.log('This will not fire, as expected');
})
.then(function(testVar) {
console.log('This also will not fire, as expected');
})
.then(testMethod1)
.then(testMethod2(testVar))
.catch(function(error) {
console.log('Error:::', error, ' , as expected');
});
function errorOnPurpose() {
return new Promise(function(resolve, reject) {
return reject('This promise returns a rejection');
});
}
function testMethod1() {
console.log('This one will not fire either, as expected');
}
function testMethod2(foo) {
console.log('This will fire!!!!, ARE YOU KIDDING ME!! WHY??');
}
Results in the console:
This will fire!!!!, ARE YOU KIDDING ME!! WHY??
Error::: This promise returns a rejection , as expected
.then(testMethod2(testVar)) In this method you are not passing the testMethod2 function to then, you are passing its response (Because in Javascript you call a function by writing funcName(funcParam))
to pass the function with some parameters you have to call it like this:
.then(testMethod2.bind(this, testVar))
Function.prototype.bind
This has nothing to do with promises.
You are invoking the method immediately: testMethod2(testVar)
Then you are passing the return value of that method invocation to then.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
I need to get the response.data out of the promise so it can be returned by the enclosing function. I know, I probably can't do it the way I've coded it because of normal JavaScript scope. Is there any way, it can be done?
The console.log at #1 produces the correct data. console.log #2 always produces 'a';
function addSiteParentId(nodeId) {
var theParentId = 'a';
var parentId = relationsManagerResource.GetParentId(nodeId)
.then(function(response){
theParentId = response.data;
console.log(theParentId); // #1
});
console.log(theParentId); // #2
return theParentId;
}
Any pointers would be appreciated.
One of the fundamental principles behind a promise is that it's handled asynchronously. This means that you cannot create a promise and then immediately use its result synchronously in your code (e.g. it's not possible to return the result of a promise from within the function that initiated the promise).
What you likely want to do instead is to return the entire promise itself. Then whatever function needs its result can call .then() on the promise, and the result will be there when the promise has been resolved.
Here is a resource from HTML5Rocks that goes over the lifecycle of a promise, and how its output is resolved asynchronously:
https://web.dev/promises/
I also don't like using a function to handle a property which has been resolved again and again in every controller and service. Seem I'm not alone :D
Don't tried to get result with a promise as a variable, of course no way. But I found and use a solution below to access to the result as a property.
Firstly, write result to a property of your service:
app.factory('your_factory',function(){
var theParentIdResult = null;
var factoryReturn = {
theParentId: theParentIdResult,
addSiteParentId : addSiteParentId
};
return factoryReturn;
function addSiteParentId(nodeId) {
var theParentId = 'a';
var parentId = relationsManagerResource.GetParentId(nodeId)
.then(function(response){
factoryReturn.theParentIdResult = response.data;
console.log(theParentId); // #1
});
}
})
Now, we just need to ensure that method addSiteParentId always be resolved before we accessed to property theParentId. We can achieve this by using some ways.
Use resolve in router method:
resolve: {
parentId: function (your_factory) {
your_factory.addSiteParentId();
}
}
then in controller and other services used in your router, just call your_factory.theParentId to get your property.
Referce here for more information:
http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx
Use run method of app to resolve your service.
app.run(function (your_factory) { your_factory.addSiteParentId(); })
Inject it in the first controller or services of the controller. In the controller we can call all required init services. Then all remain controllers as children of main controller can be accessed to this property normally as you want.
Chose your ways depend on your context depend on scope of your variable and reading frequency of your variable.
You have to return a promise instead of a variable.
So in your function just return:
return relationsManagerResource.GetParentId(nodeId)
And later resolve the returned promise.
Or you can make another deferred and resolve theParentId with it.
This question already has answers here:
jQuery.when - Callback for when ALL Deferreds are no longer 'unresolved' (either resolved or rejected)?
(8 answers)
Closed 7 years ago.
In my code below, if any defer fails it goes to fail block and everything is lost. What I want here is , to ignore failed ones and grab successful ones. Any graceful way to do it? and How would I go to failed block if all defers fail.
One work around could be to take a for loop and process deferredItems array in that loop one by one, but that is not graceful way to do it.
$.when.apply($, deferredItems).done(function(){
}).fail(function(errorObj) {
});
You can use .always, and then find the ones which were resolved, as you suggested
$.when.apply($, deferredItems).always(function(){
var resolvedDeferreds = $.grep(deferredItems, function(deferred){
return deferred.state() === 'resolved';
});
//do stuff with resolved deferreds
})
Edit:
It turns out this isn't going to work. The .always callback gets called immediately once one deferred fails and doesn't wait for the remaining pending deferreds. It looks like there's no way to wait for an array of defereds to all get either resolved or rejected using just jquery.when as is.
Use .always()
$.map([a, b], function(d) {
$.when(d).always(function(data) {
console.log(data)
})
})
This question already has answers here:
jQuery deferreds and promises - .then() vs .done()
(11 answers)
Closed 7 years ago.
There is not much answer for this simple question that I have. My main question is that I have seen the .then method used a lot in JavaScript and I know the main thing where randomobject.then(//This returns success, //this returns failure). But there are things that I don't get such as the code here:
var success = function (response) {
return response.data;
};
var error = function (errResponse) {
$log.error(errResponse.data.Message);
};
function getsomeData() {
var url = baseUrl + 'api/somedata';
return $http.get(url).then(success, error);
}
First off in that code I'm wondering how the var success knows what data it is getting and the same with error. It says response.data but what is response? It's probably the result of the http.get but that doesn't make much sense code wise. Also it seems that when I have a function for example.
getsomeData returns what it returns. Why doesn't it work if I do the ff:
var dataHolder = randomAngularService.getsomeData()
it returns an object that holds a data under $$state but somehow the .then makes it work if you do the ff:
randomAngularService.getsomeData().then(function (response) {
if(response != null) {
console.log('got the data');
$scope.meeData = response;
}
});
I thought the .then only takes two parameters? This is what's confusing me.
Also is the .then property a JavaScript method or a jQuery one?
It's used to replace (or provide an alternate way) the old callback mechanism with a cleaner way to handle asynchronous requests, instead of passing your callbacks as parameters, you can chain your function with .then, given function will be executed once the promise gets resolved.
Anyhow, this is just a basic explanation, you should really get into the books of promises for more info.
I'm lazy to explain the whole promise thing, but just to answer question about .then
The 2 arguments inside .then actually means "call this function when the promise is resolved(success)/rejected(failed)"
About the arguments inside the functions, they should be specified in the API, because the caller (for instance $http.get) get to decide what to pass when calling that function.
This question already has an answer here:
How to return fully resolved promise?
(1 answer)
Closed 7 years ago.
I use a method that expects a promise. Sometimes however, the promise is resolved instantly. Currently, if the promise is resolved right away, I still pass the promise, and use the following:
function instantAction()
{
var defer = $q.defer();
// Actions that are performed instantly
defer.resolve();
return defer.promise;
}
If there a way, to just return the resolve directly, such as something along the lines of return $q.resolve() and skip those two extra lines?
As #Blackhole and #ExpertSystem said above,
$q.when(<Data or 3rd-party Promise>) will return a promise.
It's intended to make an Angular promise out of data or a 3rd party promise.
See the docs here