Why async and await?
If you have a scenario where B depends on A and C depends on B, then we can only implement it through promise then. Such readability will become very poor, and is not conducive to flow control, for example, I want to go to B in a certain condition without executing C, this will become not very easy to control!
<script> Promise.resolve(data) .then(data1 => { // do something }) .then(data2 => { // do something }).catch(err => { Console. log(err)}) // async/await Async () => {try {const data1 = await promise.resolve (data); async () => {try {const data1 = await promise.resolve (data); // do something const resB = await Promise.resolve(data1); // do something } catch (err) { console.log(err) } } </script>Copy the code
Async and await are two new keywords in ES7. They borrow from the actual development of generators in ES6 to simplify the use of the Promise API, not to replace promises.
1.async
The purpose is to simplify the creation of promises in the return value of a function. Async is used to modify functions (whether function literals or function expressions), placed at the beginning of the function, and the return result of the modified function must be a Promise object.
<script> async function test1() { console.log(1); return 2; Function test1() {return new Promise((resolve, reject) => {console.log(1); resolve(2); }) } </script>Copy the code
2.await
Await keyword must appear in async function!! Await is used before an expression, and if the expression is a Promise, you get the state data in Thenable.
<script> async function test1() { console.log(1); return 2; } async function test2() { const result = await test1(); console.log(result); Function test1() {return new Promise((resolve, reject) => {console.log(1); resolve(2); }) } function test2() { return new Promise((resolve, reject) => { test1().then(data => { const result = data; console.log(result); resolve(); Async function test2() {const result = await 1; console.log(result); Async function test2() {const result = await promise.resolve (1); console.log(result); } async function test2() {try {const result = await test1(); console.log(result); } catch (err) { console.log(err) } } </script>Copy the code
3. Handle initial problem with async/await:
<script> // async/await Async () => {try {const data1 = await promise.resolve (data); async () => {try {const data1 = await promise.resolve (data); // do something const resB = await Promise.resolve(data1); // do something } catch (err) { console.log(err) } } </script>Copy the code
Note: If the expression of await is not a Promise, it will be wrapped in promise.resolve and run according to the rule. Exception catching can only be done by try/catch.
4. Generators simulate async and await
Generator (Generator)
A Generator is an object created by the constructor Generator, which is both an iterator and an iterable
<script> function* test() {console.log(" first run ") yield 1; Console. log(" second run ") yield 2; Console. log(" third run ") // return 10; } test(); const generator = test(); console.log(generator) </script>Copy the code
Call the next method
B. How to create a generator?
To create a Generator, you must use Generator functions
C. How to write a generator function (asterisk *)?
This is a generator function that must return a generator
function* method(){
// ...
}
Copy the code
<script> const arr1 = [1, 2, 3, 4, 5]; const arr2 = [6, 7, 8, 9]; Function * createIterator(arr) {for (const item of arr) {yield item; } } const iter1 = createIterator(arr1); // generator const iter2 = createIterator(arr2); // generator // console.log(iter1); // console.log(iter2); Function * t1() {yield "a" yield "b"} function* test() {yield* t1(); Yield "a"; // yield "b"; yield 1; yield 2; yield 3; } const generator = test(); </script>Copy the code
5. How are generator functions executed internally?
1). Inside a generator function is the data supplied for each iteration of the generator
2). Each call to the generator’s next method causes the generator function to run to the next yield keyword
3).yield is a keyword that can only be used inside a generator function to “produce” an iteration of data.
What are the details to pay attention to?
1). Generator functions can have a return value that appears in the value attribute when done is true the first time
Function * test() {console.log(" first run "); yield 1; Console. log(" second run "); yield 2; Console. log(" third run "); return 10; } const generator = test();Copy the code
2). When you call the generator’s next method, you can pass parameters that are passed to the yield expression’s return value
3). The first time the next method is called, passing arguments makes no sense
function* test() {
console.log("start");
let info = yield 1;
console.log(info);
info = yield 2 + info;
console.log(info);
}
const generator = test();
Copy the code
4). Inside a generator function, you can call other generator functions, but note the asterisk
6. Other apis for generators
– Return method: Call this method to prematurely terminate the generator function, thus prematurely ending the entire iteration process
Put return first
Put return after
-throw method: Call this method, which can produce an error in the generator
Iterators:
The process of retrieving data continuously from a data set in a specified order
<script> const arr = [1, 2, 3, 4, 5]; Arr const iterator = {I: 0, next() {var result = {value: arr[this. I], done: this.i >= arr.length } this.i++; return result; }} // let data = iterator.next(); let data = iterator.next(); while (! Data = iterator.next(); data = iterator.next(); data = iterator.next(); } console.log(" iteration complete ") </script>Copy the code
B. What is the difference between iteration and traversal?
Iteration emphasizes the sequential fetching of data, and does not guarantee the fetching of how much or all the data. Traversal emphasizes the sequential fetching of all the data
C. Iterators and iterators create functions
– Iterator: an object with a next method that returns the next data and indicates whether the iteration is complete
– Iterator creator (iterator Creator) : A function that returns an iterator
<script> // A simple iterator creates a function const arr1 = [1, 2, 3, 4, 5]; const arr2 = [6, 7, 8, 9]; CreateIterator (arr) {let I = 0; Return {next() {var result = {value: arr[I], done: I >= arr.length} I ++; return result; // function* createIterator(arr) {// for (const item of arr) {// yield item; // } // } const iter1 = createIterator(arr1).next(); const iter2 = createIterator(arr2); </script>Copy the code
D. Iterative mode (specification) :
– Iterators should have the ability to get the next data
– Iterators should have the ability to determine if there is any subsequent data
E.js specifies that if an object has a next method and the method returns an object, the object has the following format:
{value: value, done: done}, the object is considered an iterator
8. Next method:
To get the next piece of data
– Returned object value: the value of the next data – done: Boolean, whether the iteration is complete
Iterable protocol:
ES6 states that an object is iterable if it has a well-known symbolic attribute, symbol. iterator, and the attribute value is an iterator creation function.
Well-known symbols: Well-known symbols are shared symbols with a particular meaning (the same Symbol can be obtained based on a Symbol name (Symbol description), symbol.for (” Symbol name/Symbol description “)), obtained through the static property of Symbol, which defines the static members of the constructor.
Let’s just imagine if the generator could automate all iteration tasks, and the next iteration was decided by the Promise, then we could implement async/await.
9. Generator implements async
<script> const fn1 = () => new Promise(resolve => setTimeout(() => resolve("data1"), 1000)); const fn2 = () => new Promise(resolve => setTimeout(() => resolve("data2"), 1000)); function runAsync(generatorFunc) { const generator = generatorFunc(); let result = generator.next(); // Start task (start iteration), get iteration data handleResult(); Function handleResult() {if (result.done) {return; } // The iteration is not completed, which can be divided into two cases //1. If (result.value && result.value.then && typeof result.value.then === "function") {//1. Result.value. then(data => {result = generator.next(data) handleResult(); Result = generator.next(result.value) handleResult(); }} function* test() {// await const data1 = yield fn1(); console.log('data: ', data1); const data2 = yield fn2() console.log('data2: ', data2); } runAsync(test); </script>Copy the code