I thought I had a good understanding of Node and Promises but I got into this problem when I was trying to explain something for a friend of mine.
My question for you guys, is what is the expected output of this small script?
const myPromise = new Promise((resolve, reject) => {
console.log("inside promise")
resolve("Lol!")
})
setTimeout(() => {}, 100)
myPromise.then(() => console.log("then!"))
console.log("finished")
My expected output:
inside promise
finished
My thought was that if the promise was being immediately executed once defined, then it should take less than 100ms to read the then, making it obsolete. But I guess I was wrong:
Actual output:
inside promise
finished
then!
If I emit the resolve("Lol!")
though the expected output matches the actual output.
Can anybody explain me what is happening here?
Thanks!
CodePudding user response:
Here is your example annotated:
console.log('Before myPromise is created');
const myPromise = new Promise((resolve, reject) => {
// This is executed immediately when a new
// Promise is created, so it will appear
// BEFORE 'After myPromise is created'.
console.log("Inside promise")
// This passes the value "Lol!" to
// the 'then' function. By itself it
// does not console log anything.
resolve("Lol!")
})
console.log('After myPromise is created');
// This does nothing, code immediately
// carries on executing. After >=100ms a function
// doing nothing is called.
setTimeout(() => {}, 100)
// The 'then' is passed the argument of
// `resolve()` (in this case "Lol!")
myPromise.then(resolveArg => console.log(resolveArg))
// Second to last console log because
// all .then() handlers are called asynchronously
// once the main thread is idle (as the Promises/A
// spec says, when the JS engine returns back to
// "platform code"). Therefore "Lol!" will be the
// last thing logged.
console.log("Finished")
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
JS promise gives you the option to run code asynchronously. So you signal the JS engine that you would like to preform an action once another action is finished. Since actions can be successful or not promises can be resolved (resolve
) or rejected (reject
). For handling success you use then
for handling fail you use catch
, optional after both you can use finally
.
So when you declare a promise the JS engine knows it is not something you need now, rather later. So it first runs through the commands you gave it synchronously, in you case all except the then
. Once done it will check if it has promises that already had been resolved, if yes it will execute the relevant than
.
The resolve()
puts the then
of the promise to the callback queue. Later on when the call-stack will be empty the engine will handle that. Same would go for reject()
but with catch
.
If you would like to keep a cleaner syntax I recommend to check async-await.
*also note that your setTimeout
is not giving you anything. If you put console.log
in it, it will also be shown only after the 'finish'.
CodePudding user response:
new Promise()
handles the operation it has to "wait for", then returns the result to the then ()
command - this is an asynchronous operation. Consider the following example:
const myPromise = (val1, val2) => {
return new Promise((resolve, reject) => {
val1 > val2
? setTimeout(() => resolve("LOL !!!"), 1500)
: reject("\"val2\" is greater than \"val1\"");
});
}
// Then you call:
myPromise(5, 1).then(
// Processing results:
function (result) {
console.log("This is result: ", result);
},
// Error handling from "reject()"
function(error) {
console.log("This is an error: ", error);
}
)
// error case:
myPromise(1, 5).then(
// Processing results:
function (result) {
console.log("This is result: ", result);
},
// Error handling from "reject()"
// the result in console.log will be first than in the case of resolve()
function(error) {
console.log("This is an error: ", error);
}
)
// Error handling with 'catch' block
myPromise(1,5)
.then((result) => console.log(result))
.catch((err) => console.log("This is error: ", err, "# with catch-block"))
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>