I've tried to understand Promise
from google source, and haven't found how it execute code asynchronously.
My understanding of asynchronous function is that code below it can be resolved at a time before it.
For example:
setTimeout(()=>{console.log("in")}, 5000);
console.log("out");
// output:
// out
// in
The second line fufilled before the first line , so I think setTimeout is an asynchronous tech. But see this code of Promise:
let p = new Promise((resolve, reject)=>{console.log('in'); resolve(1);});
console.log("out");
//in
//out
This code block is actually excuted line by line, if console.log('in'); is a time-consuming operation, the second line will be blocked until it's resolved.
We usually use Promise like this:
(new Promise(function1)).then(function2).then(function3)
Does this mean: Promise is just used to promise that function2 is executed after function1, it's not a tech to realize asynchronous ,but a method to realize synchronous (function1, function2, function3 are executed sequently).
A promise is just a way to describe a value that does not exist yet, but will arrive later. You can attach .then handlers to it, to get notified if that happens.
Does this mean: Promise is just used to promise that function2 is executed after function1?
Yes exactly, even if function1 returns it's value asynchronously (through a Promise), function2 will run only if that value is present.
it's not a tech to realize 'asynchronous' but a method to realize 'synchronous' [execution] ?
Not really. It makes little sense to wrap a value that already exists into a promise. It makes sense to wrap a callback that will call back "asynchronously" into a promise. That said, the Promise itself does not indicate wether the value it resolves to was retrieved in a synchronous or asynchronous maner.
function retrieveStuffAsynchronously() {
// direclty returns a Promise, which will then resolve with the retrieved value somewhen:
return new Promise((resolve, reject) => {
// directly executes this, the async action gets started below:
setTimeout(() => { // the first async code, this gets executed somewhen
resolve("the value"); // resolves asynchronously
}, 1000);
});
}
console.log(retrieveStuffAsynchronously()); // does return a promise immeadiately, however that promise is still pending
retrieveStuffAsynchronously().then(console.log);
Sidenote: However, Promises are guaranteed to resolve asynchronously:
const promise = new Promise((resolve, reject)=>{
console.log('one');
resolve('three');
});
promise.then(console.log); // guaranteed to be called asynchronously (not now)
console.log("two");
Related
Suppose I have the following Promise:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
const result = doSomeWork();
setTimeout(() => {
resolve(result);
}), 100);
});
}
At which point in time is doSomeWork() called? Is it immediately after or as the Promise is constructed? If not, is there something additional I need to do explicitly to make sure the body of the Promise is run?
Immediately, yes, by specification.
From the MDN:
The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object)
This is defined in the ECMAScript specification (of course, it's harder to read...) here (Step 9 as of this edit, showing that the executor is called synchronously):
Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
(my emphasis)
This guarantee may be important, for example when you're preparing several promises you then pass to all or race, or when your executors have synchronous side effects.
You can see from below the body is executed immediately just by putting synchronous code in the body rather than asynchronous:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous();
console.log("b");
The result shows the promise body is executed immediately (before 'b' is printed).
The result of the Promise is retained, to be released to a 'then' call for example:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous().then(function(pr) {
console.log("c:" + pr);
});
console.log("b");
Result:
a
b
c:promise result
Same deal with asynchronous code in the body except the indeterminate delay before the promise is fulfilled and 'then' can be called (point c). So a and b would be printed as soon as doSomethingAsynchronous() returns but c appears only when the promise is fulfilled ('resolve' is called).
What looks odd on the surface once the call to then is added, is that b is printed before c even when everything is synchronous.
Surely a would print, then c and finally b?
The reason why a, b and c are printed in that order is because no matter whether code in the body is async or sync, the then method is always called asynchronously by the Promise.
In my mind, I imagine the then method being invoked by something like setTimeout(()=>{then(pr)},0) in the Promise once resolve is called. I.e. the current execution path must complete before the function passed to then will be executed.
Not obvious from the Promise specification why it does this?
My guess is it ensures consistent behavior regarding when then is called (always after current execution thread finishes) which is presumably to allow multiple Promises to be stacked/chained together before kicking off all the then calls in succession.
Yes, when you construct a Promise the first parameter gets executed immediately.
In general, you wouldn't really use a promise in the way you did, as with your current implementation, it would still be synchronous.
You would rather implement it with a timeout, or call the resolve function as part of an ajax callback
function doSomethingAsynchronous() {
return new Promise((resolve) => {
setTimeout(function() {
const result = doSomeWork();
resolve(result);
}, 0);
});
}
The setTimeout method would then call the function at the next possible moment the event queue is free
From the EcmaScript specification
The executor function is executed immediately by the Promise
implementation, passing resolve and reject functions (the executor is
called before the Promise constructor even returns the created object)
Consider the following code:
let asyncTaskCompleted = true
const executorFunction = (resolve, reject) => {
console.log("This line will be printed as soon as we declare the promise");
if (asyncTaskCompleted) {
resolve("Pass resolved Value here");
} else {
reject("Pass reject reason here");
}
}
const myPromise = new Promise(executorFunction)
When we execute the above code, executorFunction will be called automatically as soon as we declare the Promise, without us having to explicitly invoke it.
Suppose I have the following Promise:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
const result = doSomeWork();
setTimeout(() => {
resolve(result);
}), 100);
});
}
At which point in time is doSomeWork() called? Is it immediately after or as the Promise is constructed? If not, is there something additional I need to do explicitly to make sure the body of the Promise is run?
Immediately, yes, by specification.
From the MDN:
The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object)
This is defined in the ECMAScript specification (of course, it's harder to read...) here (Step 9 as of this edit, showing that the executor is called synchronously):
Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
(my emphasis)
This guarantee may be important, for example when you're preparing several promises you then pass to all or race, or when your executors have synchronous side effects.
You can see from below the body is executed immediately just by putting synchronous code in the body rather than asynchronous:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous();
console.log("b");
The result shows the promise body is executed immediately (before 'b' is printed).
The result of the Promise is retained, to be released to a 'then' call for example:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous().then(function(pr) {
console.log("c:" + pr);
});
console.log("b");
Result:
a
b
c:promise result
Same deal with asynchronous code in the body except the indeterminate delay before the promise is fulfilled and 'then' can be called (point c). So a and b would be printed as soon as doSomethingAsynchronous() returns but c appears only when the promise is fulfilled ('resolve' is called).
What looks odd on the surface once the call to then is added, is that b is printed before c even when everything is synchronous.
Surely a would print, then c and finally b?
The reason why a, b and c are printed in that order is because no matter whether code in the body is async or sync, the then method is always called asynchronously by the Promise.
In my mind, I imagine the then method being invoked by something like setTimeout(()=>{then(pr)},0) in the Promise once resolve is called. I.e. the current execution path must complete before the function passed to then will be executed.
Not obvious from the Promise specification why it does this?
My guess is it ensures consistent behavior regarding when then is called (always after current execution thread finishes) which is presumably to allow multiple Promises to be stacked/chained together before kicking off all the then calls in succession.
Yes, when you construct a Promise the first parameter gets executed immediately.
In general, you wouldn't really use a promise in the way you did, as with your current implementation, it would still be synchronous.
You would rather implement it with a timeout, or call the resolve function as part of an ajax callback
function doSomethingAsynchronous() {
return new Promise((resolve) => {
setTimeout(function() {
const result = doSomeWork();
resolve(result);
}, 0);
});
}
The setTimeout method would then call the function at the next possible moment the event queue is free
From the EcmaScript specification
The executor function is executed immediately by the Promise
implementation, passing resolve and reject functions (the executor is
called before the Promise constructor even returns the created object)
Consider the following code:
let asyncTaskCompleted = true
const executorFunction = (resolve, reject) => {
console.log("This line will be printed as soon as we declare the promise");
if (asyncTaskCompleted) {
resolve("Pass resolved Value here");
} else {
reject("Pass reject reason here");
}
}
const myPromise = new Promise(executorFunction)
When we execute the above code, executorFunction will be called automatically as soon as we declare the Promise, without us having to explicitly invoke it.
I have lot of confusion in promise. It's a synchronous or asynchronous ?
return new Promise (function(resolved,reject){
//sync or async?
});
The function you pass into the Promise constructor runs synchronously, but anything that depends on its resolution will be called asynchronously. Even if the promise resolves immediately, any handlers will execute asynchronously (similar to when you setTimeout(fn, 0)) - the main thread runs to the end first.
This is true no matter your Javascript environment - no matter whether you're in Node or a browser.
console.log('start');
const myProm = new Promise(function(resolve, reject) {
console.log('running');
resolve();
});
myProm.then(() => console.log('resolved'));
console.log('end of main block');
Promises aren't exactly synchronous or asynchronous in and of themselves. When you create a promise the callback you pass to it is immediately executed and no other code can run until that function yields. Consider the following example:
new Promise(function(resolve, reject) {
console.log('foo');
})
console.log('bar');
The code outside the promise has to wait for the code inside the promise (which is synchronous) to complete before it can begin execution.
That said, promises are a common way of dealing with asynchronous code. The most common use case for a promise is to represent some value that's being generated or fetched in an asynchronous fashion. Logic that depends on that value can asynchronously wait until the value is available by registering a callback with .then() or related Promise methods.
This code makes it clearer:
console.log("0");
new Promise((resolve, reject) => {
console.log("1");
resolve();
}).then(() => {
console.log("2");
});
console.log("3");
The code prints: 0 1 3 2
So, then runs asynchronously while the main call back function runs synchronously.
I don't find other answers are accurate.
new Promise (executor_function)
executor_function here will run immediately as part of Promise initialization --- this means Promise init will be executed synchronously, but does not mean code inside executor_function will necessarily run synchronously, instead, code inside executor_function can also be run asynchronously, for example:
new Promise ((resolve, reject) => {
setTimeout(resolve, 1000); // wait 1s
})
When you create a promise and pass a call back to it
that callback is gonna executed immediately (sync)
const promise= new Promise(function(resolve, reject) {
//doing some logic it gonna be executed synchronously
console.log("result");
})
console.log("global log")
But when you resolve it by .then() method it will act in asynchronous way
so for example :
const promise = new Promise(function(resolve, reject) {
//doing some logic it gonna be executed synchronously
resolve("fullfiled")
})
promise.then(v => {
console.log(v)
})
console.log("global log")
Promises are like normal classes in Javascript. Assume you are creating your own Promise implementation, your promise class would roughly look like this. Notice in your constructor you are expecting a method to be passed that you call immediately passing resolve and reject as parameters.
class Promise {
constructor(method) {
method(resolve, reject)
}
resolve() { ... }
reject() { ... }
then() { ... }
}
So when you do new Promise(), you are just creating a new object. Your Promise constructor will run, and it will call the method immediately. So that is why the code inside your promise gets executed synchronously.
return new Promise (function(resolved,reject){
//sync or async?
});
If inside your function you were calling another function that was async in nature, then that another function would get executed asynchronously, otherwise, everything else gets executed synchronously.
If you had chains in promise using then, then it only gets called after your first promise has called resolve().
return new Promise (function(resolve,reject){
const a = 5*5; // sync operation.
db.save(a, function callback() { // async operation.
resolve() // tells promise to execute `then` block.
});
});
const promise = new Promise(function(resolve, reject) {
//doing some logic it gonna be executed synchronously
console.log("check")
resolve("fullfiled")
})
promise.then(v => {
console.log(v)
})
console.log("global log")
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.
Suppose I have the following Promise:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
const result = doSomeWork();
setTimeout(() => {
resolve(result);
}), 100);
});
}
At which point in time is doSomeWork() called? Is it immediately after or as the Promise is constructed? If not, is there something additional I need to do explicitly to make sure the body of the Promise is run?
Immediately, yes, by specification.
From the MDN:
The executor function is executed immediately by the Promise implementation, passing resolve and reject functions (the executor is called before the Promise constructor even returns the created object)
This is defined in the ECMAScript specification (of course, it's harder to read...) here (Step 9 as of this edit, showing that the executor is called synchronously):
Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
(my emphasis)
This guarantee may be important, for example when you're preparing several promises you then pass to all or race, or when your executors have synchronous side effects.
You can see from below the body is executed immediately just by putting synchronous code in the body rather than asynchronous:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous();
console.log("b");
The result shows the promise body is executed immediately (before 'b' is printed).
The result of the Promise is retained, to be released to a 'then' call for example:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous().then(function(pr) {
console.log("c:" + pr);
});
console.log("b");
Result:
a
b
c:promise result
Same deal with asynchronous code in the body except the indeterminate delay before the promise is fulfilled and 'then' can be called (point c). So a and b would be printed as soon as doSomethingAsynchronous() returns but c appears only when the promise is fulfilled ('resolve' is called).
What looks odd on the surface once the call to then is added, is that b is printed before c even when everything is synchronous.
Surely a would print, then c and finally b?
The reason why a, b and c are printed in that order is because no matter whether code in the body is async or sync, the then method is always called asynchronously by the Promise.
In my mind, I imagine the then method being invoked by something like setTimeout(()=>{then(pr)},0) in the Promise once resolve is called. I.e. the current execution path must complete before the function passed to then will be executed.
Not obvious from the Promise specification why it does this?
My guess is it ensures consistent behavior regarding when then is called (always after current execution thread finishes) which is presumably to allow multiple Promises to be stacked/chained together before kicking off all the then calls in succession.
Yes, when you construct a Promise the first parameter gets executed immediately.
In general, you wouldn't really use a promise in the way you did, as with your current implementation, it would still be synchronous.
You would rather implement it with a timeout, or call the resolve function as part of an ajax callback
function doSomethingAsynchronous() {
return new Promise((resolve) => {
setTimeout(function() {
const result = doSomeWork();
resolve(result);
}, 0);
});
}
The setTimeout method would then call the function at the next possible moment the event queue is free
From the EcmaScript specification
The executor function is executed immediately by the Promise
implementation, passing resolve and reject functions (the executor is
called before the Promise constructor even returns the created object)
Consider the following code:
let asyncTaskCompleted = true
const executorFunction = (resolve, reject) => {
console.log("This line will be printed as soon as we declare the promise");
if (asyncTaskCompleted) {
resolve("Pass resolved Value here");
} else {
reject("Pass reject reason here");
}
}
const myPromise = new Promise(executorFunction)
When we execute the above code, executorFunction will be called automatically as soon as we declare the Promise, without us having to explicitly invoke it.