Understanding and use of generator functions

Source: Internet
Author: User

Original: Understanding and use of 78152770Generator functions

The Generator function is an asynchronous programming solution provided by ES6.

One, asynchronous programming

1, the so-called "asynchronous", simply said that a task is divided into two paragraphs, first execute the first paragraph, and then to perform other tasks, and so ready to go back to the second paragraph.

2, asynchronous Programming Method:

(1)回调函数(2)事件监听(3)发布/订阅者(4)Promise对象

3, the so-called callback function, is to write the second paragraph in a function alone, wait until the task is re-executed, call this function directly.

The asynchronous way of the callback function is easy to form multiple nesting, multiple asynchronous operations form a strong coupling, as long as an operation needs to be modified, its upper callback function and the underlying callback function, may have to follow the modification. This situation is called "Callback function Hell" (Callback Hell).

Promise can solve the callback hell problem, the Promise object allows the callback function to be nested and changed to a chained call.

Second, what is generator?

Syntactically, it can be understood that the Generator function is a state machine that encapsulates multiple internal states.

Formally, the Generator function is a normal function.

The entire generator function is a encapsulated asynchronous task, or a container for an asynchronous task, where the asynchronous operation needs to be paused, using the yield statement.

Generator function Features:

(1) There is an asterisk (*) between the function keys and functions, and a yield expression is used internally to define different internal states.

(2) After calling the generator function, the function does not execute, nor does it return the result of the function run, but rather a pointer object pointing to the internal state.

Iii. Defining Gernerator functions
function*Fn () {//define a generator function yield  ' hello '; yield  world"; return  ' end ';} var F1 =fn (); Call the generator function Console.log (F1); fn {[[generatorstatus]:  "suspended"}console.log (F1.next ()); {value:  "Hello", Done: false}console.log (F1.next ()); {value:  "World", Done: false}console.log (F1.next ()); {value:  "end", Done: true}console.log (F1.next ()); {value:undefined, Done: true}        

However, after calling the generator function, the function does not execute, and the return is not the result of the function execution, but rather a pointer object pointing to the internal state.

Next, you must call the next method of the Walker object so that the pointer moves to the next state. That is, each time the next method is called, the internal pointer executes from the function's head or the last stop, until the next yield expression (or return statement) is encountered.

The Generator function is executed in segments, and the yield expression is the token that suspends execution, and the next method can resume execution.

The effect of suspending execution of the generator function means that the asynchronous operation can be written in the yield statement and then executed later when the next method is called. This is actually equivalent to not having to write the callback function, because the subsequent operation of the asynchronous operation can be placed under the yield statement, anyway, wait until the next method is called to execute. Therefore, one of the important practical meanings of the generator function is to handle the asynchronous operation and rewrite the callback function.

Iv. yield expressions and next () methods

The Generator function returns a Walker object that only calls the next method to traverse the next internal state, so it actually provides a function to pause execution.

The yield expression is the pause flag.

The expression after the yield expression is executed only if the next method is called and the internal pointer points to the statement.

The use of yield should be noted:

(1) The yield statement can only be used for the scope of the function*, and if the interior of function* also defines other normal functions, the yield statement is not allowed inside the function.

(2) If the yield statement participates in the operation, it must be enclosed in parentheses.

The return method differs from the next method:

1)return终结遍历,之后的yield语句都失效;next返回本次yield语句的返回值。2)return没有参数的时候,返回{ value: undefined, done: true };next没有参数的时候返回本次yield语句的返回值。3)return有参数的时候,覆盖本次yield语句的返回值,也就是说,返回{ value: 参数, done: true };next有参数的时候,覆盖上次yield语句的返回值,返回值可能跟参数有关(参数参与计算的话),也可能跟参数无关(参数不参与计算)。

The run logic for the next method of the Walker object:

(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。

Next () Method parameters
Represents the return value of the previous yield expression, so the pass-through parameter is invalid the first time the next method is used. The V8 engine directly ignores the parameters when the next method is used for the first time, and the parameters are valid only from the second time the next method is used. Semantically, the first next method is used to start the Walker object, so there is no parameter.

For...of Cycle
The iterator object that can be generated when the Generator function is automatically traversed, and the next method is no longer needed at this time. Once the done property of the return object of the next method is True,for...of, the loop is aborted and the return object is not included.

Sample Understanding Generator:

Define a generator functionfunction* foo (x) {var y =2 * (Yield (x +1));var z = yield (Y/3);return (x + y + z);}var a = foo (5);Console.log (A.next ());object{Value6,DoneFalse} The second time the next method is run without arguments, resulting in the value of Y equals2 *Undefined (that is, Nan), divided by3 or Nan after that.Console.log (A.next ());object{Value:nan,DoneFalse} The third time the next method is run without parameters, so Z equalsUndefined, the Value property of the returned object is equal to5 + NaN +Undefined, or Nan.Console.log (A.next ());object{Value:nan,DoneTruevar b = foo (5);Console.log (B.next ());// {Value6,DoneFalse} When you first call the next method of B, return x+Value of 16Console.log (B.next (12)); //{value:8, done:false} The second time call the next method, set the value of the last yield expression to 24, returns the value of Y/3 8;console.log (B.next (13)); //{value:42, done:true} call the next method for the third time, set the value of the last yield expression to 13, when x equals 5,y equals 24, so return statement is equal to 42.  

V. Examples of use of genarator functions

1. Output Fibonacci Sequence

function *fibonacci(){    let [pre, cur] = [0,1]; for(;;){ [pre, cur] = [cur, pre+cur]; yield cur; }}for(let n of fibonacci()){ if( n>1000 ) break; console.log(n);}

2. Traverse the complete binary tree

function*Preorder(Root) {Pre-sequence traversalif (root) {Yield Root.mid;yield* preorder (root.left);yield* preorder (root.right); }}function*Inorder(Root) {Middle Sequence traversalif (root) {yield* inorder (Root.left);Yield Root.mid;yield* inorder (root.right); }}function*Postorder(Root) {Post-post traversalif (root) {yield* Postorder (Root.left);yield* Postorder (root.right);Yield Root.mid; }}functionNode(left, Mid, right) {Binary Tree ConstructorsThis.left = left;This.mid = mid;This.right = right;}functionBinaryTree(arr) {Generate two fork Treeif (arr.length = =1) {ReturnNew Node (NULL, arr[0],NULL); }ReturnNew Node (BinaryTree (arr[0]), arr[1], BinaryTree (arr[2]));}Full Binary tree nodeLet BTree = BinaryTree ([[[' d '],' B ', [' E '],' A ', [[' F '],' C ', [' G ']]);Traverse resultsvar preresult = []; For (letnode of preorder (BTree)) { ////Pre-order traversal result Preresult.push (node);} Console.log (Preresult); //(7) ["A", "B", "D", "E", "C", "F", "G"]var inresult = [];  For (Letnode of Inorder (BTree)) { //middle order traversal result inresult.push (node);} Console.log (Inresult); //(7) ["D", "B", "E", "a", "F", "C", "G"]var postresult = [];  For (Letnode of Postorder (BTree)) { //post-traverse result Postresult.push (node);} Console.log (Postresult); //(7) ["D", "E", "B", "F", "G", "C", "a"]             

3, Genarator read text file by line

function* readFileByLine(){    let file = new FileReader("a.txt"); try{ while(!file.eof){ yield parseInt(file.readLine(), 10); // 使用yield表达式可以手动逐行读取文件 } }finally{ file.close(); }}var r = readFileByLine();r.next();

4. Genarator Deploying AJAX Operations

function* main(){ // 通过 Ajax 操作获取数据 var result = yield request("http://some.url"); var res = JSON.parse(result); console.log(res.value);}function request(url){ makeAjaxCall(url, function(res){ it.next(res); })}var it = main();console.log(it.next());

5, Genarator deploy iterator interface to any object

function* deployobjectinterface (obj) { Span class= "Hljs-keyword" >let keys = object.keys (obj); for (let i=0; i<keys.length; i+ +) {let key = Keys[i]; yield [Key, Obj[key];}} let obj = {name: "Cynthia", Age:21}; for (let[key, value] of deployobjectinterface (obj)) { Console.log (key, value); }//name Cynthia//age      

6. Genarator Array Deployment Iterator interface

function* Deployarrayinterface (arr) {var nextindex =0;while (Nextindex < arr.length) {Yield arr[nextindex++]; }}var arr = Deployarrayinterface ([' Name ',' Age '); Console.log (arr.next ()); //{value:  "name", done: false}console.log (Arr.next (). value); Span class= "Hljs-regexp" >//nameconsole.log (Arr.next (). done); //falseconsole.log (Arr.next (). Value); //ageconsole.log (Arr.next (). done); //trueconsole.log (Arr.next (). Value); //undefinedconsole.log (Arr.next (). done); //true         

Understanding and using the generator function

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.