The accepted answer for How do I convert an existing callback API to promises? has this example:
function getUserDataAsync(userId){
return new Promise(function(resolve,reject){
getUserData(userId,resolve,reject);
});
}
Questions:
Shouldn't the body of Promise return something, not just call getUserData (at least in practical code, not as promise demonstration exercise)?
Is this particular Promise also a closure? It seems like it closes over userId, as getUserDataAsync creates and returns a new Promise instance using userId, but I want to be sure.
Shouldn't the body of Promise return something, not just call getUserData (at least in practical code, not as promise demonstration exercise)?
No, it doesn't have to. In fact, returning a value from the Promise constructor will have no effect. Only resolve and reject functions can fulfill a Promise.
Is this particular Promise also a closure? It seems like it closes over userId, as getUserDataAsync creates and returns a new Promise instance using userId, but I want to be sure.
Yes, the function passed to the Promise constructor closes over userId.
No, it shouldn't return something, because there is nothing to return at that point in time, hence the reason you are using a promise.
Yes.
Related
Background
I am trying to learn promises, and I have a promise chain I want to improve on.
Problem
While learning how to chain promises, I fail to see why anyone would rather return a promise instead of returning it's value.
Take the following example, which uses promise chaining:
let myObj = new MyClass();
myObj.getInfo()
.then(result => writeOutput(FILE_NAME, result))
.then(console.log(FILE_NAME + " complete"))
.catch(error => console.error(error));
class MyClass{
getInfo() {
return new Promise(function(fulfil, reject) {
fulfill("I like bananas");
});
}
Here I have to chain 2 times. But if I were to directly return the result from the method getInfo() instead of returning a Promise I could potentially do something like the following:
let myObj = new MyClass();
let str = myObj.getInfo();
writeOutput(FILE_NAME, str)
.then(console.log(FILE_NAME + " complete"))
.catch(error => console.error(error));
Questions
So as you can see I am a little confused.
Given that getInfo() is in fact async, is it possible to achieve a similar code to the one in my second code sample?
If it were possible, would it be a good idea? How would you do it?
You can only return a value from some function if that value is immediately available when that function is called (on the same tick of the event loop). Remember that return is synchronous.
If it is not available right away then you can only return a promise (or you can use a callback but here you are specifically asking about promises).
For a more detailed explanation see this answer that I wrote some time ago to a question asking on how to return a result of an AJAX call from some function. I explained why you cannot return the value but you can return a promise:
jQuery: Return data after ajax call success
Here is another related answer - it got downvoted for some reason but I think it explains a similar issue that you're asking about her:
Return value in function from a promise block
I fail to see why anyone would rather return a promise instead of returning it's value.
Because you don't have the value yet.
Given that getInfo() is in fact async, is it possible to achieve a similar code to the one in my second code sample?
If it's asynchronous, it must return a promise.
A syntax that avoids then calls (but still uses and produces promises) is made possible by async/await:
async function writeInfo(FILE_NAME) {
const myObj = new MyClass();
try {
const str = await myObj.getInfo();
await writeOutput(FILE_NAME, str);
console.log(FILE_NAME + " complete");
} catch (error) {
console.error(error);
}
}
writeInfo("…");
The purpose of a promise is to say: "The data will be there sometime, just continue with your coding for now", so that your page won't get stuck for example. Basically you are using Promises for example to load something from the server.
Another way of looking at the first question ("why would anyone..."):
When you call .then or .catch on a promise, the pending promise returned from the call is appended to the end of an existing promise chain. (Allowing the "existing chain" might only contain one promise).
When you resolve (not "fulfill", you can't fulfill a promise with a promise) a promise with a promise, the promise used in resolution is inserted at the head of what remains of the promise chain.
The promise used in resolution must be fulfilled with a value before the next .then or .catch clause in the chain is called.
As I plunge into studying Promises, my understanding has halted on the following question that I do not find discussed (all I find are specific discussions of the Promise constructor, and the Promise 'then' function - but not a discussion that compares their design patterns).
1. The Promise constructor
From the MDN documentation, we have this use of the Promise constructor (with my comment added):
new Promise(function(resolve, reject) { ... }); // <-- Call this Stage 1
Function object with two arguments resolve and reject. The first
argument fulfills the promise, the second argument rejects it. We can
call these functions, once our operation is completed.
2. The then function
Moving on to the then function that can be called on a Promise object (which returns a new Promise object), we have the following function signature as described by the documentation (with my comments added):
p.then(onFulfilled, onRejected);
Chaining
Because the then method returns a Promise, you can easily chain then
calls.
var p2 = new Promise(function(resolve, reject) {
resolve(1); // <-- Stage 1 again
});
p2.then(function(value) {
console.log(value); // 1
return value + 1; // <-- Call this Stage 2
}).then(function(value) {
console.log(value); // 2
});
My question
From the above code snippet, it seems clear to me that the value passed to the resolve function in Stage 1 (in the second occurrence of resolve - beneath (2), above) is passed on to the next stage (the first then function that follows in the same code snippet). There is no return value at Stage 1. However, it is the return value at Stage 2 that is passed on to the next stage after that (the second then function).
Is this lack of correspondence between the design pattern for the creation of a Promise, and the use of the then function on an existing promise (which also returns a Promise), just a historical fluke (one requires calling a callback but returns nothing, and the other returns a value but does not call a callback)?
Or am I missing an underlying reason why the Promise constructor utilizes a different design pattern than the then function?
Bergi's answer is excellent, and has been very helpful to me. This answer is complementary to his. In order to visualize the relationship between the Promise() constructor and the then() method, I created this diagram. I hope it helps somebody... maybe even me, a few months months from now.
The main idea here is that the "executor" function passed to the Promise() constructor sets tasks in motion that will set the state of the promise; whereas the handlers you pass to then() will react to the state of the promise.
(Code examples adapted from Jake Archibald's classic tutorial.)
This is a highly simplified view of how things work, leaving out many important details. But I think if one can keep a grip on a good overview of the intended purpose, it will help avoid confusion when one gets into the details.
A couple of selected details
The executor is called immediately
One important detail is that the executor function passed to the Promise() constructor is called immediately (before the constructor returns the promise); whereas the handler functions passed to the then() method will not be called till later (if ever).
Bergi mentioned this, but I wanted to restate it without using the terms a/synchronously, which can be confused if you're not reading carefully: The distinction between a function calling something asynchronously vs. being called asynchronously is easy to gloss over in communication.
resolve() is not onFulfill()
One more detail I'd like to emphasize, because it confused me for a while, is that the resolve() and reject() callbacks passed to the Promise() constructor's executor function are not the callbacks later passed to the then() method. This seems obvious in retrospect, but the apparent connection had me spinning in circles for too long. There is definitely a connection, but it's a loose, dynamic one.
Instead, the resolve() and reject() callbacks are functions supplied by the "system", and are passed to the executor function by the Promise constructor when you create a promise. When the resolve() function is called, system code is executed that potentially changes the state of the promise and eventually leads to an onFulfilled() callback being called asynchronously. Don't think of calling resolve() as being a tight wrapper for calling onFulfill()!
There is no correspondence between the Promise constructor and the then method because they are two independent things, designed for different purposes.
The Promise constructor is only used for promisifying1 asynchronous functions. Indeed, as you say, it is built on invoking resolve/reject callbacks to asynchronously send values, and there are no return values in that case.
That the Promise constructor itself does take this "resolver" callback (to which it synchronously passes resolve and reject) is in fact an enhancement of the older deferred pattern, and bears no intended similarity to the then callbacks.
var p = new Promise(function(res, rej) { | var def = Promise.Deferred();
setTimeout(res, 100); | setTimeout(def.resolve, 100);
}); | var p = def.promise;
The then callbacks in contrast are classical asynchronous callbacks, with the additional feature that you can return from them. They are being invoked asynchronously to receive values.
p.then(function(val) { … });
To sum up the differences:
Promise is a constructor, while then is a method
Promise takes one callback, while then takes up to two
Promise invokes its callback synchronously, while then invokes its callbacks asynchronously
Promise always invokes its callback,
then might not invoke its callbacks (if the promise is not fulfilled/rejected)
Promise passes the capabilities to resolve/reject a promise to the callback,
then passes the result value / rejection reason of the promise it was called on
Promise invokes its callback for the purpose of executing side effects (call reject/resolve),
then invokes its callbacks for their result values (for chaining)
Yes, both do return promises, though they share that trait with many other functions (Promise.resolve, Promise.reject, fetch, …). In fact all of these are based on the same promise construction and resolve/reject capabilities that also the Promise constructor provides, though that's not their primary purpose. then basically offers the ability to attach onFulfilled/onRejected callbacks to an existing promise, which is rather diametral to the Promise constructor.
That both utilise callbacks is just coincidential - not a historical fluke, but rather coadaption of a language feature.
1: Ideally, you would never need this because all natively asynchronous APIs return promises
Inspired by the previous answers (I'll address the part that was most confusing to me):
The resolve and reject arguments in the Promise constructor are not functions you define. Think of them as hooks that you get to embed into your async operation code (usually you resolve with success response and reject with failure reason) , so that javascript has a way to eventually mark the Promise as Fulfilled or Rejected depending on the outcome of your async operation; once that happens, the appropriate function you defined in then(fun1, fun2) is triggered to consume the Promise (either fun1(success_response) or fun2(failure_reason), depending on whether the Promise is Fulfilled/Rejected). Since fun1 and fun2 are plain old javascript functions (they just happen to take the future outcome of your async operation as arguments), they return values (which can be undefined if you don't explicitly return).
Also see great articles by Mozilla:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
The whole point of the promise constructor executor function is to disseminate resolve and reject functions to non-promise-using code, to wrap it and convert it to use a promise. If you wanted to limit this to synchronous functions only, then yes, a return value from the function could have been used instead, but that would have been silly since the useful part is to disseminate the resolver and reject functions to code that actually runs later (way after the return), e.g. to callbacks passed in to some asynchronous API.
Here is the execution flow of Promise.
var p = new Promise((resolve, reject) =>{
console.log("1");
resolve("OK");
});
//The above code creates a promise and execustion starts immediately.
//it happens aynchronously. So the execution will not be blocked.
//Promise exustion will not wait for 'then' call on promise
console.log("2");
//The above line displays 2 on the console.
p.then((result)=>{
console.log("3");
console.log(result);
});
//The above code shoud not block execution. So it may print 4 first
// then 3
console.log("4");
I would like to get a deeper understanding of how Promises work internally.
Therefore I have some sample code:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Here a link to execute this code.
As you would predict, first p1 is resolved, afterwards p2 and in the end the final then prints the resolv value.
But the API ref states the following:
"then" returns a new promise equivalent to the value you return from
onFulfilled/onRejected after being passed through Promise.resolve
So it would be interesting to know WHEN exactly the "then" function is executed?
Because the final "then" in the code is chained to the chainPromises(), I first thought that
it would execute after the function chainPromises() returns something (in this case another promise).
If this would have been the case the "val" of the final "then" function would be the returned promise.
But instead, the final "then" waits until all promises inside the first "then" which are returned have been resolved.
This absolutely makes sense because in this way, the "then" functions can be stacked, but
I do not really get how this is done, since the API spec. does not really cover what "then" returns and when the "then" functions is executed.
Or in other words, why does the final "then" function wait until all the Promises are resolved inside the chainPromises() function instead of just waiting for the first returned object as the API doc says.
I hope I could make clear what I mean.. :)
About Promise resolution
The thing you're witnessing here is called recursive thenable resolution. The promise resolution process in the Promises/A+ specification contains the following clause:
onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)
The ES6 promise specification (promises unwrapping) contains a similar clause.
This mandates that when a resolve operation occurs: either in the promise constructor, by calling Promise.resolve or in your case in a then chain a promise implementation must recursively unwrap the returned value if it is a promise.
In practice
This means that if onFulfilled (the then) returns a value, try to "resolve" the promise value yourself thus recursively waiting for the entire chain.
This means the following:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
So for example:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
And that:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
Is it a good idea?
It's been the topic of much debate in the promises specification process a second chain method that does not exhibit this behavior was discussed but decided against (still available in Chrome, but will be removed soon). You can read about the whole debate in this esdiscuss thread. This behavior is for pragmatic reasons so you wouldn't have to manually do it.
In other languages
It's worth mentioning that other languages do not do this, neither futures in Scala or tasks in C# have this property. For example in C# you'd have to call Task.Unwrap on a task in order to wait for its chain to resolve.
Let's start with an easy perspective: "chainPromises" returns a promise, so you could look at it this way:
// Do all internal promises
var cp = chainPromises();
// After everything is finished you execute the final "then".
cp.then(function(val) {
console.log(val);
});
Generally speaking, when returning a promise from within a "then" clause, the "then" function of the encapsulating promise will be marked as finished only after the internal "then" has finished.
So, if "a" is a promise, and "b" is a promise:
// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.
var c = a.then(function () {
return b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
So the output will be:
B!
Done!
Notice btw, that if you don't "return" the internal promise, this will not be the case:
// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.
var c = a.then(function () {
// Notice we're just calling b.then, and don't "return" it.
b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Here we can't know what would be outputted first. It could be either "B!" or "Done!".
Please check the below example regarding how promises works:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
console.log('person1: shoe ticket');
console.log('person2: shoe ticket');
const promiseGirlFriendBringingTickets = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ticket');
}, 3000);
});
promiseGirlFriendBringingTickets.then((t) => {
console.log(`person3: show ${t}`);
})
console.log('person4: shoe ticket');
console.log('person5: shoe ticket');
Promise then return promise object, not promise's resolved value. I forked your JsFiddle, and added some of mine try this.
promise.then is executed right after that promise object is resolved.
I do not know how this is done in actual promises libraries, but I was able to re-create this functionality in the following way:
1) each promise has a waitingPromises property;
2) then method returns a new promise, and the original promise's waitingPromises property points to the new promise.
In this way, the chain of .then()s creates a structure that is similar to a linked list or rather a tree (each promise can have several waiting promises). A promise can be resolved only after its 'parent' promise has been resolved. The .then method itself is executed immediately, but the corresponding promise that it creates is resolved only later.
I am not sure this is a good explanation and would love to learn about other possible approaches.
Normally code is synchronous - one statement executes like (fileopen) and there is a guarantee that the next statement will execute immediately afterwards like filewrite()
but in asynchronous operations like nodejs, you should assume that
you have no idea when the operation will complete.
You can't even assume that just because you send out one request first, and another request second, that they will return in that order
Callbacks are the standard way of handling asynchrnous code in JavaScript
but promises are the best way to handle asynchronous code.
This is because callbacks make error handling difficult, and lead to ugly nested code.
which user and programmer not readble easily so promises is the way
You can think of Promise as a wrapper on some background task. It takes in a function which needs to be executed in the background.
The most appropriate place to use a promise is where some code is dependent on some background processing and it needs to know the status of the background task which was executed. For that, the background task itself accepts two callback resolve and reject in order to convey its status to the code which is dependent on it. In layman terms, this code is the one behind it in the promise chain.
When a background task invokes resolve callback with some parameter. it's marking the background operation successful and passing the result of the background operation to the next then block which will be executed next. and if it calls reject, marking it as unsuccessful then the first catch block will be executed.
In your custom promise, you can pass an error obj to the reject callback so that next catch block is aware of the error happened in the background task.
I know how to create a promise in Kris Kowal's q with var defer = Q.defer();, calling defer.resolve(); and/or defer.reject() and return defer.promise. But reading the docs, it seem's there is an alternative way to create a promise...
From the docs:
Q.Promise(resolver)
Synchronously calls resolver(resolve, reject, notify) and
returns a promise whose state is controlled by the functions passed to
resolver. This is an alternative promise-creation API that has the
same power as the deferred concept, but without introducing another
conceptual entity.
If resolver throws an exception, the returned promise will be rejected
with that thrown exception as the rejection reason.
This is, what I've tried:
function () {
return Q.Promise(function (resolve, reject) {
(...do something...)
resolve(5); // or: reject(error);
});
}
But this doesn't work as expected!
Can someone give an example, how to use Q.Promise?
UPDATE:
Thanks for downvoting! I asked for an usage example, therefore a simple "you use it in a correct way" is more helpful! Btw: it fails silently and yes, I attached an error handler!
The reason, why the function is unnamed, is that I use it together with map and reduce to create a delayed chain of promises, but it seems, the resolver functions are never called... Therefore I asked for a (again) usage example...
Looking at your 2 examples, I'm guessing you are doing this:
var q = require('q');
Therefore Q.Promise won't work, but rather q.Promise will.
I'm working with the faye browser client using promises, and I have a function that creates a faye client after doing something asynchronous, like so:
function fayeClient() {
return doSomethingAsychronous().then(function() {
var faye_client = new Faye.Client('http://localhost/faye');
return faye_client;
});
}
and I want to use it like so:
fayeClient().then(function(faye_client) {
// do something with faye_client
});
The problem is, faye_client is also a thenable, which means that the promise returned by fayeClient resolves to the value that faye_client 'resolves' to.
However, I want the promise to resolve directly to faye_client.
I can't even manually wrap the value in a promise using Promise.resolve(faye_client);, since the same promise resolution procedure is used.
I think this could indicate a misuse of thenables on faye's part, since faye_client does not represent a value which is not yet known.
Is there any way to make a promise which resolves to a value which is also a thenable?
Instead of returning faye_client directly wrap it in an object. It's ugly but it's kind of your only choice with A+ promises:
return {client: faye_client}; // no longer a thenable
Some alternative promise implementation expose a .then or .chain that doesn't recursively assimilate but honestly I'd avoid those.
What if you use the new Promise constructor to resolve the promise?
return new Promise(function(resolve, reject) {
resolve(faye_client);
});