i have question about Promises on something that is really confusing me.
The .then() method
before i will get into the thing that confusing me about the .then() method i would do a brief explanation on how the Javascript Engine works based on my knowledge.
From what i know Javascript is not a asynchronous but rather a synchronous language
The Javascript Engine works synchronously but the Javascript Engine isn't the only thing that run on the Browser
There are things like the Rendering Engine,setTimeout,HTTP Request etc
And the Javascript Engine can talk to them when we are calling a native functions for example
setTimeout
so the setTimeout
function will call a program outside of the Javascript Engine for timing
And of course when the timer will end it will send the callback to the event queue and only after the Javascript finished all the Executions context only then it will look at the event queue
Alright now let's move to Promises
My question is how .then()
knows when resolve()
was called
I have read articles and they say that .then()
works asynchronously which is sounds weird to me because Javascript is synchronous doesn't it ?
maybe i didn't understood them correctly
so i made my own assumptions on how .then()
works because i haven't found a source that gave me the feeling and confidence that i know exactly how .then()
works.
one of them(my assumptions) was that there are two stages in the .then
method
i will use this code for demonstration to explain my assumption
var myPromise = new Promise(function(resolve){
resolve('Hello Stackoverflow !');
});
myPromise.then(function(result){
console.log(result);
});
so based on my assumption the resolve('Hello Stackoverflow !')
function calls the .then
method and the
.then
check two things here are the following
1.if the callback parameter of .then()
was created
2.if the Promise status is set to resolved
and if both conditions are true then the .then()
method will insert the callback with the value Hello Stackoverflow !
to the event queue and only after all the execution context popped of the stack then it will run the callback and we will get the result Hello Stackoverflow !
again this is based only on my assumption maybe i'm totally wrong about that.
So if you examine what i just said you can reach a conclusion that the .then
method is called twice
Why ?
the first time is when the resolve function called it but not all conditions were true
the one that isn't true is that the .then
callback parameter was created but it wasn't created yet
because we haven't got to the line of code that we created the callback so the condition is false
and the second time is when we called the .then
method and created the callback and all conditions were now true so it will insert the callback to the event queue and after all the execution contexts will popped of the stack then the callback will be called
and we will get Hello Stackoverflow !
hope you understand what i tried to explain
Am i right or wrong ?
Thanks in advance for all of you :)
i have question about Promises on something that is really confusing me.
The .then() method
before i will get into the thing that confusing me about the .then() method i would do a brief explanation on how the Javascript Engine works based on my knowledge.
From what i know Javascript is not a asynchronous but rather a synchronous language
The Javascript Engine works synchronously but the Javascript Engine isn't the only thing that run on the Browser
There are things like the Rendering Engine,setTimeout,HTTP Request etc
And the Javascript Engine can talk to them when we are calling a native functions for example
setTimeout
so the setTimeout
function will call a program outside of the Javascript Engine for timing
And of course when the timer will end it will send the callback to the event queue and only after the Javascript finished all the Executions context only then it will look at the event queue
Alright now let's move to Promises
My question is how .then()
knows when resolve()
was called
I have read articles and they say that .then()
works asynchronously which is sounds weird to me because Javascript is synchronous doesn't it ?
maybe i didn't understood them correctly
so i made my own assumptions on how .then()
works because i haven't found a source that gave me the feeling and confidence that i know exactly how .then()
works.
one of them(my assumptions) was that there are two stages in the .then
method
i will use this code for demonstration to explain my assumption
var myPromise = new Promise(function(resolve){
resolve('Hello Stackoverflow !');
});
myPromise.then(function(result){
console.log(result);
});
so based on my assumption the resolve('Hello Stackoverflow !')
function calls the .then
method and the
.then
check two things here are the following
1.if the callback parameter of .then()
was created
2.if the Promise status is set to resolved
and if both conditions are true then the .then()
method will insert the callback with the value Hello Stackoverflow !
to the event queue and only after all the execution context popped of the stack then it will run the callback and we will get the result Hello Stackoverflow !
again this is based only on my assumption maybe i'm totally wrong about that.
So if you examine what i just said you can reach a conclusion that the .then
method is called twice
Why ?
the first time is when the resolve function called it but not all conditions were true
the one that isn't true is that the .then
callback parameter was created but it wasn't created yet
because we haven't got to the line of code that we created the callback so the condition is false
and the second time is when we called the .then
method and created the callback and all conditions were now true so it will insert the callback to the event queue and after all the execution contexts will popped of the stack then the callback will be called
and we will get Hello Stackoverflow !
hope you understand what i tried to explain
Am i right or wrong ?
Thanks in advance for all of you :)
Share Improve this question edited Apr 3, 2021 at 19:43 AbsoluteBeginner 2,2533 gold badges14 silver badges24 bronze badges asked Apr 3, 2021 at 18:05 CaptainMagmelaton CapCaptainMagmelaton Cap 712 silver badges5 bronze badges 6-
2
The
.then()
method is called immediately aftermyPromise
is initialized. The.then()
method and the callback passed to.then()
are two pletely different things. – Pointy Commented Apr 3, 2021 at 18:08 - 1 Callbacks scheduled using Promises are not added to the task queue - they are added to the micro-task queue. – Yousaf Commented Apr 3, 2021 at 18:10
-
2
"if both conditions are true [it] will insert the callback with the value to the event queue" - yes. But if the promise is not fulfilled yet, the
then
method just stores the callback in an internal list, so that it can be put in the event queue by theresolve
call. – Bergi Commented Apr 3, 2021 at 19:15 - may I suggest reading answer on same topic. – Syed Commented Apr 4, 2021 at 12:20
- for some odd reasons we seem to miss the concept of WEB API that is now part of Js engine here is very good article as whats happening behind the scene through web API promise is part of thread pool for web API which makes asynchronous like operative dev.to/steelvoltage/… – Syed Commented Apr 4, 2021 at 12:27
4 Answers
Reset to default 3you can reach a conclusion that the
.then
method is called twice
This is not true. The then
method is called just like any method is called: when the statement/expression having that method call is evaluated in the normal execution flow.
The order of synchronous execution of your example is as follows:
The callback function
function(resolve) {...}
is passed to thePromise
constructor function.This constructor immediately executes the callback it receives as argument, passing it a
resolve
andreject
argument.resolve
is called, passing it the string.The promise implementation, that implemented the
resolve
function, is therefore notified and sets the state of the promise object to fulfilled, and registers the value it is fulfilled with (the string).The promise constructor finishes execution and returns the promise instance, which is assigned to
var myPromise
The callback function
function(result) {...}
is passed to themyPromise.then()
method.The native
then
implementation registers the callback, but does not execute it. As the promise is resolved, this callback is put on the promise job queue.The native
then
function finishes execution and returns a new promise. Your script does not capture this return value, so let's just label this new promise aspromiseB
.The scripts ends, leaving the call stack empty.
Now we get to what is monly called the asynchronous execution part, which always starts with an entry in a job/event queue:
The host will check which job queues have entries, giving precedence to job queues that have a high priority. A Promise job queue has a very high priority, typically higher than the event queue that deals with user interaction or other external events. So, the job that was put in the queue at step 7 above, is taken out of the Promise Job queue.
The above job executes.
If more
then
calls had been made on this promise then also those callback functions that have been registered asthen
callback (such as the one registered in step 7) on themyPromise
object and have a corresponding entry in the promise job queue. NB: I am ignoring theasync
/await
syntax here, to keep it simple.So in this case the only
then
-callback in your script is executed -- not to be confused with thethen
method itself (which was already executed in step 6). Thethen
-callback is executed with as argument the value that the promisemyPromise
was fulfilled with (the string that was registered in step 4).console.log
is executed.the
then
callback finishes execution and returnsundefined
.promiseB
is fulfilled with this return value (undefined
in this case).The job execution finishes. The call stack is empty again.
so based on my assumption the resolve('Hello Stackoverflow !') function calls the
.then
method and the.then
check two things here are the following
wrong, the resolve callback doesn't call the .then
method. you first need to understand how promises work.
while creating a promise object, we provide a execution function to the promise constructor.
const promise = new Promise (
() => {} // execution function
)
the Promise contructor will pass 2 argument (i.e. 2 callback function) to this execution function and invoke it. thus we write 2 parameter (usually named resolve, reject) to use this arguments
const promise = new Promise (
(resolve, reject) => {} // resolve and reject parameter catches the argument provided to the executor function
)
when Promise constructor invokes this execution function, depending on your logic either resolve or reject will be called (with a single argument). if resolve is called, promise state will be set to fulfiled. else if reject is called, promise state will be set to rejected.
- when this promise is settled (i.e. either fulfiled or rejected), it will add the stored callback functions to the microtask queue
to use/consume the promise, you use methods provided by the promise object, ex: .then
method. when you use .then
method, if promise is in pending state, the .then
method stores the callback in the promise object
promise.then(
val => console.log(val); // this callback function will be stored in the pending promise object, else if is already settled callback will be added to the microtask queue
)
else if promise is already settled, callback function will be added to the microtask queue
Note: if you are chaining another .then
method, it's callback will appended to the new promise object that has been returned by the previous .then
method
.catch
method works same way as.then
method
A very basic barebone implementation of Promise, which may answer your question:
class Promise {
constructor(fn) {
this.status = "PENDING";
this.result = null;
this.successCB = [];
this.errorCB = [];
fn(this.resolve, this.reject); // This actually goes into microtask
}
resolve = data => {
this.status = "SUCCESS";
this.result = data;
this.successCB.forEach(eachCB => eachCB(data));
this.successCB = [];
};
reject = error => {
this.status = "FAILED";
this.result = error;
this.errorCB.forEach(eachCB => eachCB(error));
this.errorCB = [];
};
then = (successCB, errorCB) => {
switch (this.status) {
case "PENDING":
this.successCB.push(successCB);
this.errorCB.push(errorCB);
break;
case "SUCCESS":
successCB(this.result);
break;
case "FAILED":
errorCB(this.result);
break;
default:
break;
}
};
}
To keep it simple I haven't considered chaining promises or advanced error handling. But this should work when then
is executed before/after resolve was plete.
We need to differentiate between registering a callback and calling the callback. When you do:
/*...*/.then(yourfunction);
then you have two functions in question. First, yourfunction
is a function (the callback) that you pass to the .then()
. And, the .then()
is also a function
.
And now is the best moment to clarify that even though Javascript is a synchronous language, it lets you do things asynchronously. Events are being picked up by the event handler.
Example 1
function handleSuccess(value) {
console.log(`Success, the result is ${value}`);
}
function handleFailure(reason) {
console.log(`Failure, the reason is ${reason}`);
}
new Promise((resolve, reject) => {
resolve(5);
}).then(handleSuccess, handleFailure);
new Promise((resolve, reject) => {
reject("some problem");
}).then(handleSuccess, handleFailure);
We see that upon calling resolve
or reject
, the corresponding callback is triggered.
Example 2
new Promise((resolve, reject) => {
setTimeout(() => [resolve, reject][parseInt(Math.random() * 2)](Math.random() * 1000), 1000);
}).then(handleSuccess, handleFailure);
function handleSuccess(value) {
console.log(`Success, the result is ${value}`);
}
function handleFailure(reason) {
console.log(`Failure, the reason is ${reason}`);
}
The example above is working asynchronously. We can see that the success or failure handler is being handled exactly when the promise is either handled or failed.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744399210a4572302.html
评论列表(0条)