es6 + best entry practices (10)

10.Generator

10.1. What is the generator?

The Generator function is an asynchronous programming solution provided by ES6. It encapsulates multiple states inside it, so it can be understood as a state machine. After executing the Generator function, it returns an iterator object, which can be used to traverse the internal state of the Generator function

The differences between the Generator function and the traditional function are as follows: 1. When defining a function, the function keyword is followed by "*", 2. Inside, the yield keyword is used to define the internal state

function* HelloGenerator() {
    yield "Status 1";
    yield "Status 2";
    yield "Status 3";
    yield "Status 4";
}

let hg = HelloGenerator();
console.log(hg.next());  //{value: "state 1", done: false}
console.log(hg.next());  //{value: "state 2", done: false}
console.log(hg.next());  //{value: "state 3", done: false}
console.log(hg.next());  //{value: "state 4", done: false}
console.log(hg.next());  //{value: undefined, done: true}

When the Generator function is called, it will not be executed immediately, but will pause after encountering the yield keyword. What it returns is not the result of the function, but a pointer object (Iterator object) executing the internal state

Note 1: parameters can be passed in the next method. The value of this parameter is the return value of the last state

function* HelloGenerator() {
    let result = yield "Status 1";
    console.log(result);
    yield "Status 2";
    yield "Status 3";
    yield "Status 4";
}

let hg = HelloGenerator();
console.log(hg.next());
console.log(hg.next('nodeing'));  

Note 2: you can use for...of to traverse the internal state of the Generator

function* HelloGenerator() {

    yield "Status 1";
    yield "Status 2";
    yield "Status 3";
    yield "Status 4";
}

let hg = HelloGenerator();

for( let i of hg){
    console.log(i);
}

Note 3: the object does not have the Symbol.Iterator property. We can add it manually to have the Iterator interface

let obj = {};
function* gen() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
}
obj[Symbol.iterator] = gen;

for(let a of obj){
    console.log(a);
}

10.2.Generator application

1. Limit the number of sweepstakes

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="btn">Luck draw</button>
<input type="text" id="ipt">
<script>
    let oBtn = document.getElementById('btn');
    let oIpt = document.getElementById('ipt');
    let start = gen(5);
    let timmer = null;
    oBtn.onclick = () => {
        start.next();
    };
    function draw(count) {
        clearInterval(timmer);
        let num = Math.floor(Math.random() * 30);
        let prize = 0;

        timmer = setInterval(()=>{
            prize++;
            if( num === prize){
                clearInterval(timmer);
                alert("You can still smoke."+count+"second");
                return;
            }
            oIpt.value = prize;
        }, 100);

    }

    function* gen(count) {
        while (count > 0){
            count--;
            yield draw(count);
        }
    }
</script>
</body>
</html>

2. Asynchronous read file

const fs = require('fs');

function readFile(path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, (err, data) => {
            if(err){
                reject(err)
            }else {
                resolve(data)
            }
        })
    })
}

function* asyncFile() {
    yield readFile('a.txt');
    yield readFile('b.txt');
    yield readFile('c.txt');
}

let gen = asyncFile();
gen.next().value.then((data)=>{
    console.log(data.toString());
    return gen.next().value;
}).then((data2)=>{
    console.log(data2.toString());
    return gen.next().value;
}).then((data3)=>{
    console.log(data3.toString())

});

If you think the above method is troublesome, we can introduce a co module to let the code in aysncFile execute automatically

const co = require('co');

function* asyncFile() {
    let a = yield readFile('a.txt');
    let b = yield readFile('b.txt');
    let c = yield readFile('c.txt');
    console.log(a.toString(), b.toString(), c.toString())
}
co(asyncFile()).then(()=>{
    console.log('File read complete')
});

Video tutorial address: http://edu.nodeing.com/course/50

Tags: Javascript Programming

Posted on Mon, 02 Dec 2019 18:59:01 -0500 by examancer