Study of Promises / A + ------ reference standard

      

     As part of Modern JavaScript infrastructure, Promises extremely important in terms of front-end developers. It is the basis for async / await syntax is the standard form of treatment asynchronous JavaScript. And the future of Web API, as long as asynchronous, will be to Promises appear in the form.

1, to achieve Promises / A + specifications

1.1, preliminary work

An open standard for sound, interoperable JavaScript promises https://promisesaplus.com

Through the above address, you can view the content specification.

By npm install promises-aplus-tests, you can download the test suite.

 

 

 

   By npm run test run the test suite.

1.2, understand that the term

 

 

 

A first portion of the specification, the meaning of several terms describe.

promise is then a function of objects or methods, the method compliant behavior specified.

thenable then is a method and contains object or function.

JS value is any legal value.

exception is the throw statement of values.

reason why the promise is a value indication is rejected.

This section does not need to be implemented to place the code, read on.

1.3 Promise state

 

 

 promise has three states, namely pending, fulfilled and rejected.

In the pending state, promise to be fulfilled to switch or rejected.

In fulfilled state, can not migrate to other states, there must be a non-variable value.

In rejected state, can not migrate to other states, there must be immutable reason.

 

 

 

To implement the code as above, probably:

There are three constants pending, fulfilled, rejected,

Promise a constructor , and there result two state attributes.

When the state is fulfilled, result value as a treat.

When the state is rejected, result viewed as a reason.

A transition state transition function, it will only be when the state is pending, state transition.

As, in fact, not much space for free play. Regardless of who is going to write, it is only the variable name, small differences in the number of lines of code.

1.4, Then method

 

 

 

promise must then approach accepts onFulfilled and onRejected parameters.

It was like below, then add a prototype of a method.

 

 

 

onFulfilled and onRejected case of a function must be performed at most once.

onFulfilled parameter is value, is a function of the parameters onRejected reason.

then the method can be called many times, each time a registered group onFulfilled and onRejected the callback. If they are called, must be called in accordance with the registration order.

 

 It's like above, a new record for the callbacks array of Promise.

 

 

 then the method must return promise.

Then realized that the rich into the following:

 

 Then in the method, return new Promise (f), then must return to meet the requirements of promise.

When the state is in the pending state, it is stored into the callbacks list.

When the state is not a pending state, it throws handleCallback to deal with.

As for what handleCallback Yes. Is not important, we just need to know that it must exist. We gotta do some processing, then the function is not written in the dead, or on the outside of the auxiliary function in.

As for why a setTimeout to set it?

Since then method where there is an important constraint is:

onFulfilled or onRejected must not be called until the execution context stack contains only platform code.

We do not realize Promises in the JS engine level, but the use JS to achieve JS Promises. JS was not in active control of their own execution context stack. We can indirectly via the API setTimeout / nextTick etc., here chosen setTimeout.

then the method returns the promise, also have their own state and result. They will onFulfilled appointment and conduct of onRejected.

 

 This is handleCallback do part.

 

 

handleCallback function, according to the state of state, judgment is fulfilled walking path or paths rejected.

First determine onFulfilled / onRejected is a function of whether, and if so, to return their value, the promise as the next result.

If not, a direct result of the current promise as a promise of the next result.

If onFulfilled / execution process onRejected throwing error, then this error, as the rejected reason under a promise to use.

The method then uses the core is configured under a promise of the result.

Our code, almost no extra processing logic, loyal complete specification specifies the behavior.

1.4、The Promise Resolution Procedure

From the above screenshot, we see The Promise Resolution Procedure argument.

It describes that when some special value is resolve, to do special treatment. This special treatment, specification also explicitly described.

 

 The first step, if the result is the current promise itself, it throws a TypeError.

 

 The second step, if the result is another promise, then follow the state and result of its status.

 

 

The third step, if the result is a thenable object. Then take the first function, then the function call then re-enter The Promise Resolution Procedure process.

Finally, if the above is not the case, the result of become the result promise.

 

 

By drawing up the code, as shown above, the order specification describes the preparation of 3 if.

The first judgment result is not the promise itself, it is to throw a TypeError.

The second determination result is not the type of promise, it is invoked then (resolve, reject) to take its value or reason.

The third determination result is not thenable objects, the then is taken out on the first, and then go into the new Promise The Promise Resolution Procedure procedure.

If not, then directly resolve result.

1.5, the remainder of the integration

So far, all the important parts, have been processed.

1) We have a transition to a single promise a state transition.

2) We have handleCallback, the state passed between the current and next promise a promise.

3) We have resolvePromise, the result of special special treatment.

Next, we just need to put it all together, you can link up the various parts.

Wherein, Promise constructor, following expansion:

 

 

OnFulfilled fulfilled configured to switch to the state, configured to switch to onRejected rejected state.

Configuration and resolve reject function in the resolve function, the value to be verified by resolvePromise.

With ignore this flag, to ensure the resolve / reject only one call to action.

Finally, the resolve / reject as a parameter passed in the function f.

If f function execution error, the error will be used as a reason reject.

 

 

transition as a function of the expansion, when the state changes, clear all asynchronous callbacks.

 Before we have achieved handleCallback, achieve handleCallbacks only one cycle.

 

 After running the test suite, all passing.

 

1.6、ES2015 Promises

Promises / A + specifications with ES2015 Promises are not completely equivalent. A + in the specification, the catch methods, static methods and Promsie.resolve, Promise.reject, Promise.all, Promise.race and the like is not described.

Even, new Promise This usage is not the content of A + standard, but now we just use ES2015 Promises style to achieve.

Compatible ES2015 Promises Promises / A + specification, and do their own expansion.

With the method then, we can easily implement several methods ES2015 Promises of expansion.

 

 The method and realization catch resolve / reject static methods shown above. Realization of Promise.all and Promise.race

2.2, promises to be more advanced than the asynchronous callback program?

callback -> promise -> generator -> async/await

2.2.1, promises also belongs to a callback style of

In Promises / A + specification in the first paragraph, we can see a clear statement:

 

 then promise by the method to register callbacks, wherein onFulfilled callback process value, the process onRejected callback reason.

 callback style, the kind generally refers nodejs Error-First Callbacks, or other raw callback.

 

 

2.2.2, generator function is also a callback style

Based generator + promise of asynchronous solution that can be implemented with synchronous writing, write asynchronous code in effect. For example, with the co tj library:

  1. co(function* () {

  2. var result = yield Promise.resolve(true);

  3. return result;

  4. }).then(function (value) {

  5. console.log(value);

  6. }, function (err) {

  7. console.error(err.stack);

  8. })

2.3, async / await an asynchronous ultimate solution?

I'm not sure when people say async / await an asynchronous is the ultimate solution, the ultimate measure described in any dimension.

2.3.1 generator function is more pervasive than async function

Semantic and standardization does not mean empowerment, it can also lead to diminished capacity.

async / await a diminished capacity case.

generator function that can support synchronous behavior, but also to support asynchronous behavior.

async function supports only asynchronous behavior.

For the co tj library is, promise but it's main asynchronous data sources, co'll get the results asynchronous data from other sources. For example thunk function.

 

 

 

As described above, when a yield thunk function, passed CO.'S style nodejs done this callback function.

If you prefer, we can also support the observable yield rxjs and other objects.

This is because co is a library where it can take advantage of all the characteristics of the generator function as much as possible, to achieve the desired expansion capabilities.

The async / await a new syntax, it must be built on a standardized basis, it must have the same semantics. It needs to do a lot of choice, by dropping support for non-standard objects, in exchange for clear semantics.

Thus, async / await asynchronous data results can only be obtained from the subject promise, as compared to a co reduce the capacity.

2.3.2 Bare written promise more flexible than async / await

Although more than 90% under asynchronous scene, async / await can be competent; however, there are some scenes, bare promise to write more flexible.

The most typical case is the promise of parallel processing.

 

 

Above, await keyword always serial, when we want to in order to obtain a, b, write up is very simple. If we want to get a and b simultaneously and wait for the result, await keyword was difficult to handle.

We have Promise.all by itself in a single package a plurality of promise.

 

 There was a proposal, as the syntactic sugar Promise.all. However, I did not get landingawait*

 

 

Think carefully, it is easy to understand why the practice of the figure, it is difficult landing. Promise.all only one combination of the combinations promise, there Promise.race, Promise.allSettled like.

If a symbol is assigned to each combination as syntactic sugar, more difficult to read the code.

Therefore, when you need to combine multiple promise, promise is a bare-write the necessary measures.

Further, async / await grammar, not the value, so it can not be stored and transmitted. And promise objects, may be stored in memory, can be passed as a parameter in the function.

This flexibility, in some special scenes, can bring convenience. For example, we can cache the results by caching asynchronous promise.

 

 

 

As shown above, we have created a map, store url -> promise mapping. Each time url get, check are cached.

By async / await grammar, then, promise object is hidden. We can not get. Up and other results are returned, the cache url -> result of the mapping.

However, this approach is caching coverage voids. When the process get requests trigger, but the results have not arrived in, and triggered several identical requests, these requests can not hit the cache.

If we promise is cached object, the object can call then using the promise of characteristics method multiple times, we can do all get url with an asynchronous request to get results.

2.3.3 Bare write callback is more flexible than promise

Only then promise of support onFulfilled and onRejected two kinds callback path, it belongs to simplify the callback for all possible paths.

Such as the previously mentioned rxjs, observer and subscriber has {next, error, complete} three callback path, can handle more cases than promise.

If you prefer to manually manage callback, in theory, we can do more powerful and flexible than promise.

For example cyclejs proposed by the authors callbag mode, only the combination of multiple callback functions, on the realization of rxjs-like observables and iterables.

 

 

Interested students can visit the link above to learn callbag.

Inspired by the callbag, rxjs v7.0 version you are using a similar pattern, internal reconstruction. They call this mode Functional Observables.

 

We can see, async / await but one expression is the weakest capacity, callback is one of the strongest.

Asynchronous JavaScript program evolution history:

Raw Callback Style -> Promise Callback Style -> Generator Callback Style -> Async/Await Callback

Not the ability to express growing process, but the friendliness of the developers of the growing process.

Rxjs Callback Style support because there is no syntactic sugar, and operators very much, famous for novice friendly, it has been difficult to become mainstream programs.

The Callbag Style is more human, even the source code is not conducive to reading. Only suitable written by experienced developers, hidden inside the library / framework.

2.3.4 syntactic sugar at a price

So far, we know async / await grammar can be seen as a combination of syntactic sugar more callback functions, you can simplify the complexity of the asynchronous code we write.

However, it is not without cost.

JS compiler needs to handle a large number of scenarios, to identify keywords, to be accurate throw error handling differences asynchronous and synchronous throw error of. / Await sorted out general coordination function works trophies generator function to coordinate the work to make async.

async / await + generator function in turn a new composition async generator function, the asynchronous generator.

 

 

As shown above, the async generators + for-await grammar, we can simultaneously obtain async / await asynchronous processing power, and generator output power of multiple values.

 

 

In JavaScript, there are many types of functions:

1) plain function Normal function 2) arrow function function arrow 3) generator function generator function 4) async function asynchronous function 5) async arrow function asynchronous function arrow 6) async generator function asynchronous generator function

We are constantly new function types and syntax, and iterative optimization compiler presents enormous challenges, but also new features of ECMAScript language poses a problem. So we can see async arrow function, but did not see the generator arrow function, as well as async generator arrow function.

In the future to add more function type, with permutations and combinations before the function type, the number will be more and more, to coordinate a variety of types of functions will become increasingly difficult.

Paper comprising the above described features Algebraic Effects Koka language, can simulate many features including async / await including by algebraic effect handlers, rather than provided as a library of language syntax. Does not significantly increase the burden on compiler.

React upcoming Suspense characteristics, namely the use of the above capabilities within it by JS in some of the more hack way to simulate Algebraic Effects. It can be achieved not require await an asynchronous operation, but also through some way to get the asynchronous result in the render function in the same time without compromising power requirements render function.

 

Guess you like

Origin www.cnblogs.com/zhouyideboke/p/11712823.html