Here is my piece of Vanilla TS code that I am trying to understand:
console.log("-------------------------- (LOG 1)");
setTimeout(() => console.log("-----------------------------(LOG 2)"), 1000);
const fetchedData = fetch("https://pokeapi.co/api/v2/pokemon/ditto");
const fnReturningNewPromise = () => {
return new Promise<string>((resolve, reject) => {
if (1 == 1) {
console.log("LOG 3 - new Promise in return Statement");
resolve("fnReturningNewPromise - resolved");
}
reject("fnReturningNewPromise - rejected");
});
};
const customPromise = new Promise<string>((resolve, reject) => {
if (1 === 1) {
console.log("LOG 4 - new Promise");
resolve("Promise resolved");
} else {
reject("REJECTED");
}
});
fetchedData
.then((res) => {
console.log("LOG 5 - fetchedData 1st then - res.json()");
return res.json();
})
.then((data) => console.log("LOG 6 - with fetching"));
Promise.resolve(1).then((res) =>
console.log("LOG 7 - immidielty resolved", res)
);
customPromise
.then((response) => response)
.then((data) => console.log("LOG 8 - without fetching"));
console.log("LOG 9 - sync code");
setTimeout(() => {
console.log("LOG 10 - setTimeout - immidietly resolved");
}, 0);
fnReturningNewPromise().then((res) =>
console.log("LOG 11 - resolving promise returned from fn: ", res)
);
And this is the ouput from the console:
-------------------------- (LOG 1)
LOG 4 - new Promise
LOG 9 - sync code
LOG 3 - new Promise in return Statement
LOG 7 - immidielty resolved 1
LOG 11 - resolving promise returned from fn: fnReturningNewPromise - resolved
LOG 8 - without fetching
LOG 10 - setTimeout - immidietly resolved
LOG 5 - fetchedData 1st then - res.json()
LOG 6 - with fetching
-----------------------------(LOG 2)
I try to find out where the order of this logs come from. Here are my questions:
I got confused - can anyone explain it to me?
I tried to output the result in the console.log however the final effect confused me even more
Promise executor functions are executed synchronously.
So going through the code looking for synchronously executed code the logs are
"-------------------------- (LOG 1)"
"log 4 - new Promise" from the executor of custom promise
"log 9 - sync code" from inline code
"LOG 3 - new Promise in return Statement", from a promise executor in a synchronously called function ("in return statement" is not an exact description).
Jobs in the promise job queue are executed before tasks sourced from the the timer task queue
So looking through for jobs placed in the promise job queue (i.e. the microtask queue) next we get
Jobs in the promise job queue can add more jobs to run before the queue becomes empty
So next we get jobs placed in the promise job queue by promise jobs in the queue that have already been executed:
Timout callback jobs have lower priority than jobs in the Promise jobs queue
So now timeout handlers from the timer task source can be executed because the promise job queue is empty:
"LOG 10 - setTimeout - immidietly resolved")
Logs from fetching
When logs from the fetch operation appear depends on how long the operation takes to complete, but
From actual output they appear within less than a second.
Tech notes
The task of running a promise handler to monitor its behavior and continue chained promise handling is called a "Promise job" in the above because that is what it is called in ECMAScript standards.
Jobs in the Promise Job Queue get their priority over other tasks because they are implemented in HTML5 using the microtask queue.