I have such method in my factory
getTogether() {
let promise = this._$q.all([this._$http.get('/groups'), this._$http.get('/tasks')]);
return promise
.then((data) => {
//local variable for reduce server<->client
this._localList = data;
return this._localList;
});
};
and I call this method in my controller.
this._boardFactory.getTogether().then((list) => {
console.log(list)
});
all works perfectly, however I don't understand one thing.
what's the difference between return promise and return promise.then?
thanks for your attantion
If you only do return promise in your code, you will return the resolution of the promise object. However, if you do return promise.then you will return the resolution of the promise from the then clause.
then returns a promise, so promise.then will execute promise then execute the then clause returning that promise.
More info on then here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
I say Promise is object and then() is method on Promise object which reruns another Promise.
Promise.prototype.then(onFulfilled, onRejected)- Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler, or to its original settled value if the promise was not handled (i.e. if the relevant handler onFulfilled or onRejected is not a function).
Below image explains thing :
Read : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
this is how it gose
-Promise - let this is ajax call,
- then() - now this allows you to work on the output you received from first promise
- then() - now if you want to work on the output of second promise which return by then(first)
- then - another promise allows to wok on ouput of third
so it kind of chaining ...go on ..till you complete it
Related
I've been trying to figure this one out and I'm wondering how the resolution value gets passed too getAnswer's then call. First I return the result of add which I think returns a Promise which allows me to use a then call on the then method on getAnswer, but then how does the second return statement get passed to it?
function add(num1, num2) {
return new Promise((resolve, reject) => {
setTimeout(() => {resolve(num1 + num2);}, 500)
});
}
function getAnswer() {
return add(5, 5).then((res) => {
console.log(res);
return new Promise((resolve, reject) => {
resolve("How does this get passed too getAnswer's then function?");
});
});
}
getAnswer().then((res) => {
console.log(res);
})
The Basics:
add returns a Promise -- which is an instance of the Promise object, every instance of Promise has a then method which you can use to observe that promise's resolution.
For chaining purposes, then has been designed in such a way that it returns a Promise itself (so, every then call in JavaScript will always return a new promise). The promise returned by then will be resolved with the return value of its handlers (more on this later).
Now, when you say:
return add(5, 5).then((res) => {
console.log(res);
return new Promise((resolve, reject) => {
resolve("How does this get passed too getAnswer's then function?");
});
});
You are not returning add's result, you are returning the promise that you created by calling then on add's result (this is just standard JS behavior).
Your Question:
but then how does the second return statement get passed to it?
Here is what the then method returns, according to MDN (the parts inside ([]) are my additions):
A Promise in the pending status ([this is what your first return statement is actually returning]). The handler function (onFulfilled or onRejected) gets then called asynchronously ([the handler in your example is the function you've passed to the then inside getAnswer]). After the invocation of the handler function, if the handler function:
returns a value, the promise returned by then gets resolved with the returned value as its value;
throws an error, the promise returned by then gets rejected with the thrown error as its value;
([this is your case -- your second return]) returns an already resolved promise, the promise returned by then gets resolved with that promise's value as its value;
returns an already rejected promise, the promise returned by then gets rejected with that promise's value as its value.
returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the resolution/rejection of the promise returned by the handler. Also, the value of the promise returned by then will be the same as the value of the promise returned by the handler.
Personally, whenever I see a Promise being returned by then's handlers, I just assume -- to simplify the situation for my mind -- that the Promise returned by then originally has been replaced with the Promise that was just returned by one of then's handlers. Of course, this mental mapping is parallel to the actual functionality, AFAIK.
So, to sum it up:
getAnswer returns a promise -- created by add(5, 5).then(...).
you then observe that returned promise using then (getAnswer().then(...)) -- unrelated here, but this call also creates a promise.
it happens that the handler for the observation of the promise returned by the add call (this handler is the function you pass to then in #1) returns a promise as well, and the rules are that if a handler of then returns a promise p, then whenever p is resolved with a value v, the original promise -- created by then -- will be resolved with v as well.
Finally, the handler you passed to the then in #2 to observe the promise returned by getAnswer() will be called with the value v from #3.
Feel free to ask for any clarifications, but before doing so, read this article thoroughly.
I want to fulfill a promise with some other promise. The point is that I really want to get access to the (still pending) second promise as soon as the first promise is fulfilled. Unfortunately, I only seem to be able to get the second promise's resolution value once both both promises are fulfilled.
Here's the use case that I have in mind:
var picker = pickFile();
picker.then( // Wait for the user to pick a file.
function(downloadProgress) {
// The user picked a file. The file may not be available just yet (e.g.,
// if it has to be downloaded over the network) but we can already ask
// the user some more questions while the file is being obtained in the
// background.
...do some more user interaction...
return downloadProgress;
}
).then( // Wait for the download (if any) to complete.
function(file) {
// Do something with the file.
}
)
The function pickFile displays a file picker where the user may pick a file either from their own hard drive or from a URL. It returns a promise picker that is fulfilled as soon as the user has picked a file. At this point, we may still have to download the selected file over the network. Therefore, I cannot fulfill picker with the selected file as resolution value. Instead, picker should be fulfilled with another promise, downloadProgress, which in turn will eventually be fulfilled with the selected file.
For completenes, here's a mock implementation of the pickFile function:
function pickFile() {
...display the file picker...
var resolveP1 = null;
var p1 = new Promise(
function(resolve, reject) {
resolveP1 = resolve;
}
);
// Mock code to pretend the user picked a file
window.setTimeout(function() {
var p2 = Promise.resolve('thefile');
resolveP1(p2); // <--- PROBLEM: I actually want to *fulfill* p1 with p2
}, 3000);
return p1;
}
The problem in the marked line is that I would like to fulfill the promise p1 with the new promise p2, but I only know how to resolve it. The difference between fulfilling and resolving is that resolving first checks if the supplied value p2 is again a promise. If it is, then fulfillment of p1 will be deferred until p2 is fulfilld, and then p1 will be fulfilled with p2's resolution value instead of p2 itself.
I could work around this issue by building a wrapper around p2, i.e. by replacing the line
resolveP1(p2); // <--- PROBLEM: I actually want to *fulfill* p1 with p2
from the second code example by
resolveP1({promise: p2});
Then, in the first code example, I'd have to replace the line
return downloadProgress;
by
return downloadProgress.promise;
But this seems like a bit of a hack when all I really want to do is just fulfill (instead of resolve) a promise.
I'd appreciate any suggestions.
There doesn't seem to be a solution apart from the workaround I already described in the question. For future reference, if you want to fulfill (rather than resolve) a promise p with a value val, where val is another promise, then just calling the promise resolution function for p with argument val won't work as expected. It would cause p to be "locked in" on the state of val, such that p will be fulfilled with val's resolution value once val is fulfilled (see spec).
Instead, wrap val in another object and resolve p with that object:
var resolveP; // Promise resolution function for p
var p = new Promise(
function(resolve, reject) {
resolveP = resolve;
}
);
function fulfillPwithPromise(val) { // Fulfills p with a promise val
resolveP({promise: val});
}
p.then(function(res) {
// Do something as soon as p is fulfilled...
return res.promise;
}).then(function(res) {
// Do something as soon as the second promise is fulfilled...
});
This solution works if you already know that val is a promise. If you cannot make any assumptions about val's type, then you seem to be out of luck. Either you have to always wrap promise resolution values in another object, or you can try to detect whether val has a field then of type "function" and wrap it conditionally.
That said, in some cases the default behavior of promise resolution may actually have the desired effect. So only use the workaround described above if you are sure that you want to fulfill instead of resolve the first promise with the second one.
Although different people use different terms, in common terminology, "fulfill" means to put a promise in the "success" state (as opposed to "reject")--the state that will trigger then then handlers hanging off it.
In other words, you cannot "fulfill" a promise with a promise. You can fulfill it with a value. (By the way, the term "resolve" is usually meant as either of fulfilling or rejecting.)
What you can do is return a promise from a .then handler and that will have the effect of essentially replacing the original promise with the returned promise.
Here is a simple example of doing that:
asyncTask1 . then(asyncTask2) . then(processData)
where asyncTask1 is a promise, and asyncTask2 is a function which returns a promise. So when asyncTask1 is fulfilled (done successfully), then asyncTask2 runs, and the promise returned by the .then is "taken over" by the promise asyncTask2 returns, so that when it finishes, the data can be processed.
I can do something similar by calling Promise.resolve with a promise as parameter. It's a bit of a misnomer, because I'm not resolving the promise in the technical sense. Instead, the new promise created is "inhabited" by the promise I passed in. It's also useless, because using the result is exactly the same as using the promise I passed in:
Promise.resolve(asyncTask2)
behaves exactly the same as
asyncTask2
(assuming asyncTask2 is already a promise; otherwise Promise.resolve has the effect of creating a promise which is immediately fulfilled with the passed in value.)
Just as you can pass a promise to Promise.resolve, you can pass a promise to the resolve function provided to you as a parameter of the promise constructor callback. If the parameter you pass to resolve is a non-promise, the promise immediately fulfills with that value. However, if the parameter you pass to resolve is another promise, that promise "takes over the body" of the promise you are constructing. To put it another way, the promise you are constructing starts to behave exactly as the the promise passed to resolve.
By "behave exactly" I mean, if the promise you pass in to resolve is already fulfilled, the promise you are constructing is instantly fulfilled with the same value. If the promise you pass in to resolve is already rejected, the promise you are constructing is instantly rejected with the same reason. If the promise you pass in to resolve is not resolved yet, then any then handlers you hang off the promise you are constructing will be invoked if and when the promise you pass to resolve is resolved.
Just as it is confusing that Promise.resolve may result in a promise which is not actually resolved, it is similarly confusing that calling the resolve function handed to you as a parameter to the promise constructor may not actually resolve the promise being constructed if you call it with an unresolved promise. Instead, as I've said a couple of times now, it has the effect of putting the promise being constructed in a state of total congruence with the promise passed to resolve.
Therefore, unless I am missing the point of your question, pickfile could be written as
function pickFile() {
return new Promise(function(resolve, reject) {
...display the file picker...
// Mock code to pretend the user picked a file
window.setTimeout(function() {
resolve('thefile');
});
}
I didn't really understand your question clearly, so this might not be what you want. Please clarify if you care to.
Found a similar solution in the process of moving away from Angular's $q to the native Promise feature. Promise.all could be an option (in cases of independent parallel async tasks) by passing around an appropriate object, or something decorated with the state, passing it off to whatever is ready when appropriate. In the Promise.all sample below note how it recovers in one of the promises--took me awhile to realize how to redirect the result of a chain. The result of the all is just the last promise's return. While this doesn't answer the question's title, using return Promise.reject(<an-object-including-a-promise>) (or resolve) gives a series and/or group of async tasks shared access and control along the way. In the case of picking, downloading then working with a file I'd take out the progress-event handling then do: pickFile.then(download,orFailGracefully) with downloadProgress handled within the download onResolve handler (download-progress doesn't appear to be an async task). Below are related experiments in the console.
var q = {
defer: function _defer(){
var deferred = { };
deferred.promise = new Promise(function(resolve, reject){
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
};
var communityThatCares = q.defer();
communityThatCares.promise.then(function(someGood){
console.log('someGood', someGood);
return someGood;
}, function(someBad){
console.warn('someBad', someBad);
return someBad;
});
(new Promise(function(resolve, reject){ communityThatCares.about = 'communityThatCares'; setTimeout(resolve,1000, communityThatCares); }))
.then(
function(e){
console.log(3,e); return e.resolve(e);
}, function(e){
console.warn(3, e); return e.reject(e);
});
var todo = {
find:'swan'
};
var greaterGood = [(
(new Promise(function(res,rej){ res(todo); })).then(function(e){ e.stuff = 'things'; return e; }),
(new Promise(function(res,reject){
reject(todo);
})).then(function(e){ return e; }
,function(e){
console.warn(1,e);
e.recover = 'uh oh';
return Promise.resolve(e);
}).then(function(e){ console.log(2,e); return e; }),
(new Promise(function(res,rej){ res(todo); })).then(function(e){ console.log(1,e); e.schedule = 'today'; return e; },function(e){ console.warn(1,e); return e; }).then(function(e){ console.log(2,e); return e; }))
];
var nkay = Promise.all( greaterGood )
.then(function(todo){
console.log('all',todo[0]); return todo;
}, function(todo){
console.warn('all',todo[0]); return todo;
});
What is the difference between
resolve and onFulfilled in javascript promises ?
Similarly, what is the difference between
reject and onRejected ?
In simple words, I would just ask how does onsuccess callback of Promise.then(onsuccess, onreject) differs from Promise.resolve ()?
I am reading Javascript with Promises by Daniel Parker.
The book has mentioned both of them but I have not realized the difference between two yet.
While describing then in promises:
promise.then
promise.then([onFulfilled], [onRejected]) returns promise
The promise.then() method accepts an onFulfilled callback and an
onRejected
callback. People generally register onRejected callbacks using promise.catch()
instead of passing a second argument to then . The function then returns a promise that is resolved by the return value of the
onFulfilled or onRejected callback. Any error thrown inside the callback rejects the new promise with that error.
Also,
Promise.resolve
Promise.resolve([value|promise]) returns promise The Promise.resolve()
function is a convenience function for creating a promise that is
already resolved with a given value. If you pass a promise as the
argument to Promise.resolve(), the new promise is bound to the promise
you provided and it will be fulfilled or rejected accordingly.
Code:
function settled(promises) {
var alwaysFulfilled = promises.map(function (p) {
return p.then(
function onFulfilled(value) {
return { state: 'fulfilled', value: value };
},
function onRejected(reason) {
return { state: 'rejected', reason: reason };
}
);
});
return Promise.all(alwaysFulfilled);
}
};
simply put
when a promise is resolved any current or future onFullfilled functions will be called with the parameter to that function being the value of the resolve function
similarly with reject/onRejected
This question already has answers here:
How angular promise .then works
(2 answers)
Closed 7 years ago.
All:
I am pretty new to Promise, just curious how they get resolved, one thing confuse me is:
Some posts show using
var defer = $q.defer();
// some logic block
{
// if success doing something
defer.resolve();
}
return defer.promise;
But if use .then() function, promise is returned from .then(function(){}), I wonder how do I control if this promise resolved or not?
Another confuse is: If I use some chained .then() function, I wonder what is the relationship between them, are they same promise object which is just passed down or each .then will generate a new Promise object and return it?
As specified in this throughout and clear document:
QUESTION 1. I wonder how do I control if this promise resolved or not?
One of the Promise APIs support pecial functions that resolve() or reject() a Promise. So you may use the following functions in your code
var promise = new Promise(function(resolve, reject) {
// do a thing, possibly async, then…
if (/* everything turned out fine */) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
});
Rejections happen when a promise is explicitly rejected, but also implicitly
if an error is thrown in the constructor callback.
var jsonPromise = new Promise(function(resolve, reject) {
// JSON.parse throws an error if you feed it some
// invalid JSON, so this implicitly rejects:
resolve(JSON.parse("This ain't JSON"));
});
jsonPromise.then(function(data) {
// This never happens:
console.log("It worked!", data);
}).catch(function(err) {
// Instead, this happens:
console.log("It failed!", err);
});
In other variants the Promise is resolved with the return value that is passed to the next link in the chain.
QUESTION 2.
Promises are in some sense functions that will result in the future with some value. The result value is the return value from promise - so basically promise chaining ( .then(...).then... ) are chain of functions that wait till the previous one will end ( resolve with some value ). Then they are called with an argument which is the return value of the last executed function in the queue ( previous link in the chain ).
.then() returns a new promise object thus allowing chaining. (see remark for documentation link)
REMARK
There is great and small description of all Angular promises in official documentation under the section Promise API and next one - Chaining the promises.
This isn't an attempt to explain promises in their full glory - there are blogs for that. This is to answer your specific questions:
Q1:
But if I use .then() function, promise is returned from .then(function(){}), I wonder how do I control if this promise resolved or not?
The resolve handler function of .then controls how this promise is resolved:
If the handler function returns a non-promise value, then the promise with resolve with that value.
var thenPromise = originalPromise.then(function success() {
return "foo";
});
thenPromise.then(function(data){
console.log(data); // "foo"
});
If the handler function returns another promise, then the .then promise will resolve exactly how the new promise would resolve (or reject)
var thenPromise = originalPromise.then(function() {
return $timeout(function(){ return "foo"; }, 1000);
});
thenPromise.then(function(data){
console.log(data); // (after 1 second) "foo"
});
If the handler function throws an exception or if the the return is an explicitly rejected promise `$q.reject:
var thenPromise = originalPromise.then(function() {
return $q.reject("some error");
});
thenPromise.then(function(data){
console.log(data); // doesn't get here
})
.catch(function(err){
console.log(err); // "some error"
});
Q2:
If I use some chained .then() function, I wonder what is the relationship between them, are they same promise object which is just passed down or each .then will generate a new Promise object and return it?
Each .then generates its own promise.
var timeoutPromise = $timeout(afterTimeout, 1000);
var thenPromise = timeoutPromise.then(doSomething);
var anotherThenPromise = timeoutPromise.then(doSomethingElse);
If timeoutPromise resolves, then both doSomething and doSomethingElse would execute and depending on their outcome thenPromise and anotherThenPromise would have their respective resolutions.
According to the Promise A+ spec,
2.2.2.1 If onFulfilled is a function, it must be called after promise is fulfilled, with promise’s value as its first argument.
However, what happens if a promise is passed in .then()?
Now we have this code:
var Promise = require('bluebird');
var func1 = function() {
return new Promise(function(resolve, reject) {
resolve('hello');
});
}
var wrapper = function() {
return func1();
}
var api = function() {
return wrapper()
.then(wrapper());
}
api().then(function(msg) {
console.log(msg);
});
Why is 'hello' get printed?
In the api function, wrapper() is evaluated as a promise through func1() and get passed in .then(). Right now, this promise acts 'onFulfilled' function according to the spec quoted. However, the spec says the onFulfilled(the returned promise in this case) is expecting a parameter passed in as the value of the previous promise calling .then(). But how can the value get passed into a promise?
I am not very good at explaining things. So if you are confused, can you explain why 'hello' is printed? How?
But how can the value get passed into a promise?
It can't and the part of the spec you quoted should have already told you that:
If onFulfilled is a function [...]
a promise is a not a function! (usually, and if it were, it would act like a function, not like a promise).
So calling .then basically doesn't do anything:
2.2.7.3 If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.
promise1 is fulfilled with "hello", so that's what promise2 to is fulfilled with as well.
wrapper()/*promise 1*/.then(wrapper())/*promise 2*/.then(function(msg) {
console.log(msg);
});
is essentially
wrapper()/*promise 1*/.then(function(msg) {
console.log(msg);
});
and that's why "hello" is printed.
Now, if you passed wrapper, a function, instead, i.e. wrapper().then(wrapper).then(...), which is the same as
wrapper()/*a*/.then(function foo(result) {
return func1(); /*b*/
})/*c*/.then(function(msg) {
// ...
});
then foo would get the result from the first promise (a) (according to the part your quoted). And since the onFulfilled function returns a promise itself (b), the promise returned by .then (c) is resolved with value of that inner promise (b) (which happens to produce the same value as the first initial promise (a)).
This is described in section 2.3, where x is the value that is returned by onFulfilled.
If x is a promise, adopt its state:
If x is pending, promise must remain pending until x is fulfilled or rejected.
If/when x is fulfilled, fulfill promise with the same value.
If/when x is rejected, reject promise with the same reason.