In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly talks about "what is the difference between Promise, Generator and Async". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Next, let the editor take you to learn "what is the difference between Promise, Generator and Async?"
We know that both Promise and Async/await functions are used to solve asynchronous problems in JavaScript, from the original callback function handling async, to Promise handling async, to Generator handling async, to Async/await handling async, every technology update makes the way JavaScript handles async more elegant. at present, Async/await is considered to be the ultimate solution for asynchronous processing, making JS asynchronous processing more and more like synchronous tasks. The highest level of asynchronous programming is that there is no need to care whether it is asynchronous at all.
The Development of Asynchronous Solutions
1. Callback function
Judging from the early Javascript code, before the birth of ES6, almost all asynchronous processing was based on callback functions, and you may have seen the following code:
Ajax ('aaa', () = > {/ / callback function body ajax (' bbb', () = > {/ / callback function body ajax ('ccc', () = > {/ / callback function body})}))
Yes, before ES6, this kind of code could be seen everywhere. Although it solves the problem of asynchronous execution, it is followed by the callback hell problem that we often hear about:
There is no order to speak of: the execution of nested functions brings debugging difficulties and is not conducive to maintenance and reading
Too coupled: once there is a change in a nested level, it will affect the execution of the entire callback
Therefore, in order to solve this problem, the community first proposed and implemented Promise,ES6 to write it into the language standard and unified the usage.
2.Promise
Promise is a solution for asynchronous programming that is more reasonable and powerful than traditional solutions-callback functions and events. It is born to solve the problems caused by the callback function.
With the Promise object, asynchronous operations can be expressed as a flow of synchronous operations, avoiding layers of nested callback functions. In addition, the Promise object provides a unified interface that makes it easier to control asynchronous operations.
So we can change the above callback function to this: (provided that ajax is wrapped in Promise)
Ajax ('aaa') .then (res= > {return ajax (' bbb')}) .then (res= > {return ajax ('ccc')})
By using Promise to deal with asynchrony, it looks clearer than previous callback functions, solves the problem of callback hell, and the chained call of Promise's then is more acceptable and in line with our idea of synchronization.
But Promise also has its disadvantages:
The internal error of Promise cannot be caught by try catch, and can only be caught by the second callback of then or catch.
Let protry {pro = new Promise ((resolve,reject) = > {throw Error ('err....')})} catch (err) {console.log (' catch',err) / / will not print} pro.catch (err= > {console.log ('promise',err) / / will print})
Once a new Promise is created, it will be executed immediately and cannot be cancelled.
I have previously written an article that explains how Promise is used and how it is implemented internally. Students who don't quite understand Promise can take a look.
From how to use to how to implement a Promise
Https://juejin.cn/post/7051364317119119396
3.Generator
Generator function is an asynchronous programming solution provided by ES6, and its syntax behavior is completely different from that of traditional functions. The Generator function brings JavaScript asynchronous programming to a whole new stage.
Statement
Similar to function declarations, except that there is an asterisk between the function keyword and the function name, and yield expressions are used inside the function body to define different internal states (yield means "output" in English).
Function* gen (x) {const y = yield x + 6; return y;} / yield if used in another expression, put it in () inside / / if it is on the right side of =, do not add () function* genOne (x) {const y = `this is the first yield execution: ${yield x + 1}`; return y;}
Execution
Const g = gen (1) / / executing Generator returns an Object, instead of calling the next method of the pointer like the ordinary function that returns the value g.next () / {value: 7, done: false} / / after the return, which starts from the header of the function or where it last stopped Until the next yield expression or return statement is paused, that is, the execution of the line of yield / / returns an Object,// value after the execution of yield. Done indicates whether the function has been executed g.next () / {value: undefined, done: true} / / because the last line of return y has been executed, so done is true
After calling the Generator function, the function does not execute and does not return the result of the function run, but a pointer object to the internal state, that is, the Iterator Object object. Next, you must call the next method of the traversal object to move the pointer to the next state.
So the above callback function can be written as follows:
Function * fetch () {yield ajax ('aaa') yield ajax (' bbb') yield ajax ('ccc')} let gen = fetch () let res1 = gen.next () / / {value:' aaa', done: false} let res2 = gen.next () / / {value: 'bbb', done: false} let res3 = gen.next () / / {value:' ccc', done: false} let res4 = gen.next () / / {value: undefined Done: true} done indicates the end of execution for true
Because of the traversal object returned by the Generator function, only a call to the next method will traverse the next internal state, so it actually provides a function that can pause execution. The yield expression is the pause flag.
The running logic of the next method of the traversal object is as follows.
(1) when an yield expression is encountered, the following operation is paused and the value of the expression immediately following yield is taken as the value of the value attribute of the returned object.
(2) the next time the next method is called, continue execution until the next yield expression is encountered.
(3) if no new yield expression is encountered, it runs until the end of the function, and takes the value of the expression after the return statement as the value of the value attribute of the returned object.
(4) if the function does not have a return statement, the value attribute value of the returned object is undefined.
The yield expression itself does not return a value, or always returns undefined. The next method can take a parameter that is treated as the return value of the previous yield expression.
How do you understand this sentence? Let's look at the following example:
Function* foo (x) {var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z);} var a = foo (5); a.next () / / Object {value:6, done:false} a.next () / / Object {value:NaN, done:false} a.next () / / Object {value:NaN, done:true} var b = foo (5) B.next () / {value:6, done:false} b.next (12) / / {value:8, done:false} b.next (13) / / {value:42, done:true}
Since there is no return value for yield, the value after execution of (yield (xSecret1)) is undefined, so the second execution of a.next () is actually the execution of 2*undefined, so the value is NaN, so in the following example b, 12 is passed in the second execution of b.next (), which will be regarded as the return value of the first execution of b.next (), so it can be calculated correctly in the example of b. You can't confuse the value value in the next execution result with the yield return value. It's not the same thing.
The difference between yield and return
Similarities:
Can return the value of the expression after the statement
You can pause function execution.
Difference:
A function can have more than one yield, but only one return
Yield has location memory function, but return does not.
4.Async/await
Async/await is actually the syntax sugar of Generator above, the async function is actually equivalent to the role of funciton *, and await is equivalent to the role of yield. In the async/await mechanism, the spawn automatic execution function encapsulated above is automatically included.
So the above callback function can be written more succinctly:
Async function fetch () {await ajax ('aaa') await ajax (' bbb') await ajax ('ccc')} / / but this can be written on the premise that the three requests are interdependent, otherwise it will cause performance problems, because each request needs to wait until the last request is completed before initiating the request. If there is no interdependence, it is recommended that they initiate the request at the same time. Here you can use Promise.all () to handle the
The improvement of async function to Generator function is reflected in the following four points:
Built-in actuator: the async function executes the same as the ordinary function, unlike the Generator function, you need to call the next method or use the co module to actually execute it.
Semantics are clearer: async and await have clearer semantics than asterisks and yield. Async indicates that there is an asynchronous operation in the function, and await indicates that the following expression needs to wait for the result.
Wider applicability: the co module stipulates that yield commands can only be followed by Thunk functions or Promise objects, while the await command of async functions can be followed by Promise objects and primitive type values (numeric, string, and Boolean values, but then automatically converted to an immediate resolved Promise object).
The return value is the Promise object of the Promise:async function, which is much more convenient than the return value of the Generator function is the Iterator object. You can use the then method to specify the next step.
Async function
The return value of the async function is the Promise object, so it can call the then method
Async function fn () {return 'async'} fn () .then (res = > {console.log (res) / /' async'})
Await expression
The expression to the right of await is usually a promise object, but it can also be other values
If the expression is a promise object, await returns the value of promise success
If the expression is another value, use this value directly as the return value of await
Await is followed by a Promise object that blocks the following code, the Promise object resolve, and then gets the value of resolve as the result of the await expression.
So that's why await must be used in async. Async happens to return a Promise object that can perform blocking asynchronously.
Function fn () {return new Promise ((resolve, reject) = > {setTimeout () = > {resolve (1000)}, 1000) })} function fn1 () {return 'nanjiu'} async function fn2 () {/ / const value = await fn () / / await the right expression is Promise, and the result is Promise's successful value / / const value = await' Nanjiu const value = await fn1 () console.log ('value', value)} fn2 () / / value' nanjiu' asynchronous scheme comparison.
The latter three schemes are proposed to solve the traditional callback function, so their advantages over the callback function are self-evident. And async/await is the grammatical sugar of Generator function.
The internal error of Promise cannot be caught by try catch, so it can only be caught by the second callback of then or catch, while the error of async/await can be caught by try catch.
The Promise is executed as soon as it is created, without blocking the later code, while the await object followed by the Promise object in the async function blocks the later code.
The async function implicitly returns a promise whose promise value is the value of the function return.
Using the async function makes the code more concise, eliminating the need to call the then method to get the return value like Promise, writing anonymous functions to handle the value of Promise, defining redundant data variables, and avoiding nested code.
Said so much. By the way, take a look at the question ~ console.log ('script start') async function async1 () {await async2 () console.log (' async1 end')} async function async2 () {console.log ('async2 end')} async1 () setTimeout (function () {console.log (' setTimeout')} 0) new Promise (resolve = > {console.log ('Promise') resolve ()}) .then (function () {console.log (' promise1')}) .then (function () {console.log ('promise2')}) console.log (' script end')
Parsing:
The printing order should be: script start-> async2 end-> Promise-> script end-> async1 end-> promise1-> promise2-> setTimeout
The old rule is that the global code is executed from top to bottom, first print out script start, then execute async1 (), first encounter await async2 (), execute async2, print out async2 end, then put the code behind await into the micro-task queue, then execute new Promise, print out Promise, encounter resolve, put the first then method into the micro-task queue, and then print out script end, and the global code is finished. Then take out the first micro task from the micro task queue, print out the async1 end, then take out the second micro task for execution, print out the promise1, and then the then method is executed. The current state of Promise is fulfilled, and it can also start the callback of then, so the second then is added to the micro task queue at this time, and then the micro task execution is taken out of the micro task queue to print out the promise2. At this time, the micro task queue is listed as empty. Then execute the macro task queue and print out the setTimeout.
Problem solving skills:
Whether it is the callback content in then or catch, as long as the code executes normally or returns normally, the current new Promise instance is in fulfilled status. If an error is reported or Promise.reject () is returned, the new Promise instance is in rejected status.
Fulfilled status can trigger then callback
Rejected status can trigger catch callback
Execute the async function and return the Promise object
Await is equivalent to the then of Promise and all the contents under await under the same scope are callbacks in then.
Execute micro tasks first and then macro tasks in asynchrony
At this point, I believe you have a deeper understanding of "what is the difference between Promise, Generator and Async". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.