In-depth understanding of JS Promise

Source: Internet
Author: User
When using Promise, our simplest understanding and usage is to provide the asynchronous result to the resolve as a parameter, and then pass a custom function to the then method as the result handler function, as in the code above. But what exactly are the two parameters of resolve and reject? Behind this, what is the basic way of doing it? Let's get to know it from a normative point of view.

New Promise ((resolve, reject) = SetTimeout (resolve, +, ' foo ')   . Then (console.log)   //foo (after 1s)

Tl;dr
1, promise work mechanism and callback similar, all use the internal abstraction operation job to realize asynchronous
2. The Resolve/reject function in the Promise constructor is created internally, and the parameter passed in when it is called is the result of parsing, which is inserted into the Job queue along with the handler function that the Promise has stored. The passed in parameter can also be a promise, which is useful inside the promise.all/race.
3, Promise.prototype.then According to the state of the current Promise to determine whether the results stored in the Promise are immediately taken out and with the parameters of the processing function directly into the JOB queue or the first associated with Promise as a result handler function. Then the Promise build function is implicitly called to build a new Promise and return.
4, Promise.all first create a new Promise, and then first, initialize an empty result array and a counter to count the Promise that have been resolve, then iterate, for each iteration value it will create a Promise for it, and set the promise then to add results to the result array and counter--when the counter is reduced to 0 o'clock will resolve the final result.
5, Promise.race will also create a new main Promise, after the main is based on Promise can only resolve once the limit, for each iteration value will create another Promise, first resolve will be first Promise Resolve returns the result.

New Promise (Executor)

First of all, from the Promise constructor, it is the value of the Promise property of the global object, which is why we can invoke it directly in the browser environment, just like the constructor of String, Array.

The first step of new Promise (executor), like other constructors, is to build a new object according to Promise's prototype and initialize several internal slots [[promisestate]],[[promiseresult]],[ [Promisefullfillreactions]],[[promiserejectreactions]],[[promiseishandled]] to record some relevant information, can be roughly inferred from the name of their role, For details, we will mention the following. Here their initial values except [[[Promiseresult]] are followed by "Pending", empty list, empty list,false.

Next, ES will generate resolve function for resolve promise and reject function for promise reject based on this promise object. Then call executor, with resolve function and reject function as parameters, if there is an error in this process, reject promise directly. Finally, return to promise.

What is resolve and what is reject? We know the state of Promise, that is [[promisestate]] There are three kinds of values: Pending, fullfilled, rejected, reject function can reject Promise, the state from Pendi Ng becomes rejected. However, the Resolve function can be used to fullfill promise to pending from fullfilled to reject promise.

So what exactly does the Resolve function and reject function do?

Look at reject function first, when it is generated, it initializes [[Promise] and [[alreadyresolved]] slots, which is associated with a Promise. When executed, a parameter reason is passed in, and only if [[Alreadyresolved]] is false, which is not resolve, and the status is pending, the return rejectpromise, incoming promise, and Reason parameter to reject promise, otherwise returns undefined.
Rejectpromise (promise, Reason), in addition to the [[Promisestate]] from pending to rejected, but also the result of promise [[Promiseresult]] value is set to Reason , and will take out the existing records in promise [[Promiserejectreactions]] (it is believed that the reader has understood that there will be an operation to store records in this internal slot) and use the Triggerpromisereactions Call these records for subsequent processing, and pass in the reject reason reason. Similarly, the fullfillpromise (promise, value) operation used in resolve function changes the state of promise to fulfilled, extracting [[Promisefullfillreactions]] The value of the triggerpromisereactions is called, and the result of passing in fulfilled is value.

Triggerpromisereactions (reactions, argument) calls Enqueuejob ("Promisejobs", Promisereactionjob, <<reactions, argument>>), will be explained in detail later.

Then look at resolve function, which, like reject function, associates it with a promise when it is generated. At execution time, the parameters we pass in are called resolution. If promise has been resolve, return to undefined. After that, the situation is relatively complicated.

1, if the user passes the promise itself to the resolve function as the parameter resolution, it will create a typeerror,throw it, and call the Rejectpromise,reason parameter for this Typeerro R.
2, if the type of resolution is not an Object, call Fulfillpromise (promise, resolution).
3. The rest of the situation is that resolution is the case with the then object (Promise) in addition to itself.
If resolution is a non-then object, it rejectpromise.
If there is a then property but cannot be called, also fulfillpromise,.
If there is a then property and can be called, enqueuejob ("Promisejobs", Promiseresolvethenablejob, <<promise, resolution, thenaction> >).
Before explaining Enqueuejob, let's look at what a Job is. Simply put, it is like the internal implementation mechanism of the callback: "When no other ES is running, initialize and execute its own corresponding es." “。 We have a job queue for the FIFO to execute, and the current execution environment running execution context and execution context stack, the first of the job queue will be executed when both are empty.

ES requires at least two Job queues in the implementation, Scriptjobs and Promisejobs. When we call Enqueuejob ("Promisejobs", ...) , the Job to be completed and their parameters are inserted into the promisejobs queue. As you can see, there are two types of jobs under Promise

1, Promisereactionjob (reaction, argument)
Reaction has three internal slots [[[Capability]], [[Type]], and [[Handler]], respectively [[associated Promise and related resolve function and reject function]], [[Category]] , [[Handler]]. If the user does not give handler (undefined), the argument is treated as a result based on whether the category is Fulfill or Reject. If handler is given, it is used to further process the argument. Finally, based on this result, the Resolve function and the Reject function are processed and returned.
2, Promiseresolvethenablejob (Promisetoresolve, thenable, then)
Creates and promisetoresolve the associated resolve function and reject function. With then, the Thenable function is called, and the This,resolve function and reject function are returned for the parameter call.

Promise.prototype.then (onfulfilled, onrejected)

The first is to create a promisecapability that contains a new promise and associated resolve function and reject function. The generation of promise is like building a promise as normal with the promise constructor, but to the constructor executor is automatically created internally, the function is to put the Resolve/reject function Recorded in the promisecapability. According to Promisecapability and onfulfilled/onrejected, create two promisereaction, respectively, for fulfill and reject, which is the final operation to be performed in Promisejobs. If the current promise (this) is a pending state, insert these two reaction respectively into the promise [[Promisefulfillreactions]] and [[Promiserejectreactions]] The queue. However, if promise is already in fulfilled or rejected state, the value result is taken from promise [[Promiseresult]] and is inserted into the Job queue as a result of fulfilled/reject. , Enqueuejob ("Promisejobs", Promisereactionjob, <<reaciton, result>>), and finally return to the new store in Prjomisecapability Promise Promise.prototype.catch (onrejected) is Promise.prototype.then (Undefined, onrejected)

Promise.resolve (x)

Create a promisecapability like then, call the Resolve function directly in it and pass in the value x to be parsed, and finally return to the new promise.

Promise.all (iterable)

Promise.all will also create a promisecapability like then, which contains a new Promise and its associated resolve function and reject function, After that, the iterator loops: 1. If the iteration is over and the counter is 0, call Promisecapability's resolve function to resolve the result array 2. Otherwise the counter adds 1, and then takes out the value of the next iteration and passes it to Promise.resolve also constructs a new Promise, and then internally creates a Promise.all resolve Element Function that is passed to the new Promise and then used to add the result to the result array and subtract one from the counter.

Promise.race (iterable)
Similarly, create a promisecapability, then iterate, build a new Promise with Promise.resolve, then call the new Promise then method, pass in the promisecapability res Olve/reject function, combined with the previously mentioned promise will only resolve once, you can see that there is really race meaning.

Conclusion: see here, do not know whether we have a deeper understanding of the Promise. Another step further, ES6 in the new proposed async/await is actually applied Generator thought and Promise, interested in the words can continue to understand.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.