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
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 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
How come that all my Resolved Callbacks are properly executed but only
1 Error Callback is being run ?
In the example here if longOperation(true) I get only one error, while when run with false I get the two resolved messages. In my understanding each .then returns a new promise which is in the error state for the second .then error callback registration
This example is written using Typescript !
function longOperation(error) {
return new Promise < any > ((resolve, reject) => {
if (error) {
reject("Error")
} else {
setTimeout(function() {
resolve(true)
}, 1000)
}
})
}
let op = longOperation(true);
op
.then(result => {
console.log("Resolved #1")
}, undefined)
.then(result => {
console.log("Resolved #2")
}, undefined)
.then(undefined, error => {
console.log("Error1")
})
.then(undefined, error => {
console.log("Error2")
})
The first error handler catches the error, just like a regular catch block. If you want the chained promise to be rejected, you have to rethrow the error:
Promise.reject().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(null, e => {
console.log(3);
throw e; // <= rethrow here
}).then(null, e => {
console.log(4);
});
Promises can "recover".
The error will propagate down the chain of ".then"s until it finds an error callback. When it does it will execute the error callback and pass the return value down to the next promise's resolve method.
So only the next closest error callback to the promise will get executed.
If you want to catch all possible errors along the chain just put your error callback at the end of the chain and all errors will be handled by it.
In your code example you are actually creating 5 promises. The original one and 1 for each ".then". The 2nd and 3rd only have an onResolved method and the last two only have and onRejected method.
This is how it will be executed:
1st Promise(op): I just rejected. I see I have a deferred promise with no onRejected callback. So I'll just call it's reject method with the same value I rejected with.
2nd Promise: The previous promise called my reject method and I also have a deferred promise with no onRejected callback. So I'll just call it's reject method with the same value I rejected with.
3rd Promise: The previous promise called my reject method. I have a deferred promise too, but mine does have an onRejected callback. I,ll call the callback with the value I rejected with, and I'll call my deferred promise's resolve method with the callback's return value.
4th Promise: The previous promise called my resolve method. I have a deferred promise, but it doesn't have an onResolved callback so I'll just call it's resolved method with the value I resolved with.
5th Promise: The previous promise called my resolve method. I resolved and did nothing more because I have no deferred promise.
I know that a thenable has the then method, but how does Promise know the state of the thenable objected has moved to rejected?
Example:
Here, $.ajax is a thenable and can be ducktyped as a Promise if you do this:
Promise.resolve($.ajax({ url: '/test' }))
But how does the promise that this expression returns handle the catch case?
A Promises/A+ then method does take two callbacks - one for the fulfilment and one for the rejection case. You would not use the .then(…).catch(…) pattern but .then(…, …) - the second callback is the "catch case" (notice that .catch(…) is nothing but .then(null, …)).
This is how thenables are assimilated - when the second callback gets called, they reject the promise with the error. Example:
var rejectingPromise = Promise.resolve({
then: function(onSuccess, onError) {
onError(new Error);
}
});
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.