JavaScript Visualized - Promise Execution
Summary
TLDRThis script demystifies JavaScript Promises by explaining their creation, execution, and handling behind the scenes. It clarifies how Promises work with async tasks, the event loop, and microtask queue, using a practical example with setTimeout. The explanation simplifies Promise chaining and the non-blocking nature of asynchronous JavaScript, encouraging viewers to understand and utilize Promises effectively in their coding.
Takeaways
- 😎 Promises in JavaScript can seem intimidating but are not as complicated once you understand their mechanics.
- 🛠 A Promise is created using the `new Promise` constructor, which takes an Executor function and creates a Promise object with internal slots for state, result, and reactions.
- 🔄 The Executor function has access to `resolve` and `reject` to change the state of the Promise to 'fulfilled' or 'rejected', respectively.
- 🔗 Promises can be chained using `.then()` and `.catch()` methods, which add Promise reaction records to the Promise object.
- 📂 The microtask queue is where the asynchronous part of Promises is handled, and it gets priority over the task queue when the call stack is empty.
- 🔄 When a Promise is resolved, its reaction records' handlers are added to the microtask queue, allowing for non-blocking execution.
- 🕒 The `setTimeout` function is used in the script to demonstrate asynchronous behavior within a Promise constructor.
- 🔄 The `.then()` method not only creates a reaction record but also returns a new Promise, enabling Promise chaining.
- 🔢 The script demonstrates how Promises can be chained to incrementally process results, such as multiplying numbers in sequence.
- 📈 Real-world applications of Promises might involve image processing, where operations can be chained in a non-blocking manner.
- 📝 The script concludes with a challenge for viewers to understand the order in which numbers are logged, reinforcing the concept of Promise chaining and execution.
Q & A
What is a Promise in JavaScript?
-A Promise in JavaScript is an object that may produce a single value some time in the future. It represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to be called in the future, when the promise is fulfilled or rejected.
How is a Promise created in JavaScript?
-A Promise is created by using the `new Promise` constructor, which takes an Executor function as an argument. This Executor function itself takes two arguments, typically named `resolve` and `reject`, which are functions used to resolve or reject the promise respectively.
What are the internal states of a Promise?
-A Promise has three possible states: pending, fulfilled, and rejected. The 'pending' state is the initial state. 'Fulfilled' means that the operation completed successfully, and 'rejected' means that the operation failed.
What is the purpose of the resolve function in a Promise?
-The resolve function is used to resolve a Promise, setting its state to 'fulfilled' and assigning it a resulting value. This function is called when the asynchronous operation completes successfully.
What does the reject function do in a Promise?
-The reject function is used to reject a Promise, setting its state to 'rejected' and assigning it a resulting value that represents the reason for the rejection. This function is called when the asynchronous operation fails.
What are Promise reaction records?
-Promise reaction records are objects that are created when you chain a `then` or `catch` method to a Promise. They contain information about the handlers that will be called when the Promise is fulfilled or rejected.
How does the event loop handle Promises?
-The event loop plays a crucial role in handling Promises. When a Promise is resolved or rejected, its handlers are added to the microtask queue. Once the call stack is empty, the event loop checks the microtask queue and executes any pending microtasks.
What is the difference between the microtask queue and the task queue?
-The microtask queue is where Promise reaction handlers are placed and is processed before the task queue. The task queue, also known as the callback queue or macro task queue, is where callbacks from tasks like timers, network responses, and I/O operations are placed.
How can you chain Promises in JavaScript?
-You can chain Promises by using the `then` method. Each call to `then` returns a new Promise, which can then be followed by another `then`, allowing you to create a sequence of asynchronous operations.
What is the significance of the microtask queue in asynchronous JavaScript programming?
-The microtask queue is significant because it allows for the execution of Promise handlers as soon as possible, without blocking the main thread. This helps in keeping the script responsive and efficient.
How does the `setTimeout` function interact with Promises?
-The `setTimeout` function can be used within a Promise's Executor function to schedule an asynchronous task. When the timer completes, the callback passed to `setTimeout` is executed, which can then resolve or reject the Promise based on the result of the asynchronous task.
Outlines
🔧 Understanding JavaScript Promises
This paragraph delves into the intricacies of JavaScript promises, which are often perceived as complex but are demystified in this explanation. The author introduces the concept of promises, how they are created using the 'new Promise' constructor, and the internal workings such as the promise state, result, and reactions to fulfillment or rejection. It explains the asynchronous nature of promises, the event loop, and the microtask queue, illustrating how promises are resolved or rejected and how their reactions are handled in a non-blocking manner. The paragraph also touches on chaining promises and the incremental handling of results, providing a foundational understanding of promises in JavaScript.
🔗 Chaining Promises for Asynchronous Operations
The second paragraph builds on the understanding of promises by demonstrating how they can be chained to handle asynchronous operations incrementally. It describes a code snippet where a new promise is created and resolved immediately, followed by subsequent 'then' handlers that manipulate the resolved values in a sequence, showcasing the promise resolution process and the chaining mechanism. The paragraph emphasizes the non-blocking aspect of promise handling, which allows for maintaining script interactivity and efficiency. It also hints at practical applications, such as image processing, where promises can be used to perform a series of operations in a non-blocking manner. The author concludes with a quiz to test the viewer's comprehension of how the numbers in the code snippet are logged, reinforcing the learning with an interactive element.
Mindmap
Keywords
💡Promise
💡Executor function
💡Resolve
💡Reject
💡Promise state
💡Promise result
💡Promise reaction records
💡Microtask queue
💡Event loop
💡Chaining
💡Asynchronous task
Highlights
JavaScript Promises can be intimidating but are not as complicated as they seem when understood.
A Promise is created using the new Promise constructor with an Executor function.
The Executor function has access to resolve and reject methods to handle the Promise's state.
Promises have internal slots including state, result, and reaction records for handling.
Promise reactions are created by chaining then or catch methods, which include handler callbacks.
The event loop and microtask queue are key to the asynchronous behavior of Promises.
Resolving a Promise updates its state and result, and schedules the handler to the microtask queue.
The microtask queue is prioritized over the task queue in the event loop for asynchronous operations.
Asynchronous tasks like network requests can resolve or reject a Promise based on their outcome.
The then method not only creates a reaction record but also returns a new Promise for chaining.
Chaining then methods allows for incremental handling of Promise results in a non-blocking way.
Promises can be used to perform a series of operations in sequence without blocking the main thread.
The transcript provides a step-by-step walkthrough of how Promises are executed and handled.
The example given demonstrates how Promises can be used for image processing tasks.
The transcript aims to demystify Promises and provide a clear understanding of their inner workings.
The speaker provides additional resources, including a blog post and a link to the ECMAScript specification.
A front-end Master course is mentioned for further exploration of JavaScript internals.
Transcripts
promises in javascripts are known to be
a little daunting intimidating annoying
I don't know whatever negative thing you
want to say about them but I promise you
that once you understand what happens
behind the scenes under the hood they're
actually not that complicated so today I
want to walk you through promise
execution and see what happens behind
the scenes when we interact and work
with promises so one way to create a
promise is by using the new promise
Constructor and this Constructor also
receives an Executor function now when
the new promised Constructor is executed
a new promis object is created in memory
and this object contains some internal
slots like the promis state promis
result promis fulfill reactions promise
reject reactions and promise is handled
we also get some additional
functionality to either resolve or
reject this promise now we can resolve
this Promise by calling resolve which is
made Available To Us by the executor
function and when we call resolve the
promise state is set to fulfilled and
the promised result is set to the value
that we pass to resolve so the string
done in the this case similarly we can
reject the Promise by calling reject in
which case the promise state is said to
rejected and the promise result is set
to the value that we passed to reject so
the string fail cool nothing special
here we're just calling a function to
change some object property so what's so
special about promises well that's
actually in those two fields that we
skipped so far so in the promise fulfill
reactions and the promise reject
reactions because these fields contain
something called Promise reaction
records we can create a promise reaction
record by chaining a then or a catch
method to the promise so whenever we
chain then the then method is
responsible for creating that promise
reaction record and among many other
fields this reaction record contains a
hand layer and this has some code and
that code is that call back that we
passed to then now what happens is that
whenever we resolve the promise so we
call resolve resolve is added to the
call stack the promis state is set to
fulfill the promised result is set to
the value that we pass to resolve and
the promise reaction records Handler
receives that promis result so the
string done in this case and the Handler
is now added to the microtask CU this is
where the asynchronous part of promises
comes into play and just kind of as a
quick refresher um whenever the call
stack is empty the event Loop first
checks in the microtask que and whenever
this queue is empty it goes to the task
que also called like the Callback Q
macro task Q whatever you want to call
it what's important here is that the
microtask Q gets PR now so far I've only
been calling resolve and reject
synchronously like right in the promise
Constructor but usually you want to
initiate some kind of asynchronous task
in this Constructor with an asynchronous
task I mean anything off the main threat
So reading something from a file system
or a network request or something as
simple as a timer whenever they return
that data we can use their callback
function to either resolve with the data
that they returned or reject if an error
occurred so just to keep it simple let's
uh see how the execution goes for This
Promise Constructor so we have the
promise Constructor that has a set
timeout and we also have a then Handler
let's just go through it step by step
and see what happens so first the new
promise Constructor is added to the call
stack and this creates the promise
object the executor function is called
and on the first line we have a set
timeout so set timeout is added to the
call stack and this one is responsible
for scheduling that timer in this case
100 milliseconds and this has that call
back that we passed to set time out so
the function that eventually calls
resolve then on the next line we have
the den Handler so then is added to the
call stack and this is responsible for
creating that promis reaction record so
this creates a promise reaction record
with a call back that we provided as its
Handler now then is popped off the call
stack and let's just imagine that those
100 milliseconds are up now so the call
back that we passed to set timeout is
now added to the task Q there's nothing
on the call stack anymore script is
finished so it can now go from the task
Q to the call stack and this now calls
result so this changes the promise state
to fulfilled the promise result to the
string done and it schedules that
Handler to the microtask que result is
now done popped off the call stack so is
the call back and there's again nothing
on the call stack so the event Loop
first checks the microtas Q while there
are Handler is waiting so the Handler is
added to the call stack and this then
console logs the promised results which
is the string done now the nice thing
about the fact that it's added to the
microtask queue is that in the meantime
our script can just keep running it can
just keep performing important tasks and
it stays interactive only when the call
stack is empty so when there's like
nothing important to do does it get
added to the call stack from the micras
Q so this means that we can handle the
promise result in a nonblocking way now
another cool thing is that then itself
also returns a promise so besides just
creating that promise reaction record it
also creates a promise object and this
allows us to kind of chain those vents
to each other and have this incremental
promise results um hand
so let's just see what happens when we
have this code snippet so the first we
have the new promise Constructor which
creates that promise object this
immediately resolves with one so the
state is set to fulfilled and promised
result is one then we call the then
Handler so this creates a promised
reaction record with with the Handler
being results and then it returns result
time two result being that promised
result which is the number one but it
also creates a promis object and this is
now set to fulfilled because we returned
result time two result being one so
result time 2 is two and we do the same
on the next line so we have another then
this creates a promise reaction record
again with the exact same Handler so
result times two this time result being
two so 2 * 2 is four so This Promise
result is now four and then we have one
more and this just logs that value so
again the state is set to fulfilled in
this case the result is undefined
because we didn't return a value we're
only logging it but in the console you
will see four so that's just something
to keep in mind we can chain those dens
together and kind of incrementally
handle that promise result in a
non-blocking way now of course in a real
application you won't use numbers like
this but instead you want to
incrementally handle that promis result
maybe you have some kind of image that
you first want to resize and then add a
filter and then change the format I
don't know what you want to do with an
image but you can do all that by
chaining this then in a nonblocking way
and that's pretty cool that's pretty
pretty powerful all right so let's see
how well you understand promises or at
least how well I explained it so pause
this video real quick and see if you
know how these numbers get loged all
right so if you guessed 132 then
congrats you understood it perfectly or
it's a lucky guess I don't know but
let's see how this happened so first we
have the new promise Constructor again
added to the call stack new promise
object is created then we have the
executor function which gets added to
the call stack and on the very first
line we have console log one this gets
added through the call stack and this
logs one then we call resolve with two
so now the promise state is changed to
fulfilled the promise result is set to
two and we don't have a promise fulfill
reaction yet that only happens on the
next line resolve is popped off the call
stack so is the executor function and
the new promise Constructor now on the
next line we finally have then so this
creates that promise reaction record um
it doesn't get added to that list
because the promise is already resolved
this would just take up unnecessary
memory but it still has access to that
promised result so this promised
reaction record has the Handler with the
result being two and then console log
result so this is immediately added to
the microtask CU it's important to
remember that it's not immediately
executed no it is immediately scheduled
to the microtask CU then we go to the
next line because our script isn't done
yet the call stack isn't empty yet and
there we just call console log 3 in a
normal way so this is added to the call
stack logs three so now we have 1 three
now finally our script is done there's
nothing on the call stack so the first
task in the microtask que is added to
the call stack which is that then
Handler which then console logs the
result being two so now finally two gets
logged hopefully my explanation kind of
helped to demystify Promises at least a
little bit um I also have a written blog
post in the description if you prefer to
just read it uh I also added a a link to
the ecospec if you're like me and like
to just read the
specification for the technologies that
we're working with and if you want more
kind of questions like this I have a
front of Master course also link below
where I have a bunch of questions about
javascripts internals and also kind of
explanations like this one so you can
test your JavaScript knowledge and uh
maybe learn something new thanks and
have fun coding
浏览更多相关视频
Javascript Promises vs Async Await EXPLAINED (in 5 minutes)
Asynchrony: Under the Hood - Shelley Vohr - JSConf EU
#68 What is an Observable | Understanding Observables & RxJS | A Complete Angular Course
What the heck is the event loop anyway? | Philip Roberts | JSConf EU
Asynchronous JavaScript in ~10 Minutes - Callbacks, Promises, and Async/Await
How JavaScript Works 🔥& Execution Context | Namaste JavaScript Ep.1
5.0 / 5 (0 votes)