zoukankan      html  css  js  c++  java
  • ES6的generator

    generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。

    1、generator函数的定义是function*,这与普通函数是不同的

    2、yield需使用在generator函数中,所表示的意思是“执行到这,并返回”

    3、yield是有返回值的,其中value代表return的值,done代表函数是否执行结束。

    yield 'your value'; // { value: 'your value', done: true }

    yield; // { value: undefined, done: true }

    generator跟函数很像,定义如下:

    function* foo(x) {
        yield x + 1;
        yield x + 2;
        return x + 3;
    }

    generator和函数不同的是,generator由function*定义(注意多出的*号),并且,除了return语句,还可以用yield返回多次。用处:可以编写一个产生斐波那契数列的函数:

    function* fib(max) {
        var
            t,
            a = 0,
            b = 1,
            n = 0;
        while (n < max) {
            yield a;
            [a, b] = [b, a + b];
            n ++;
        }
        return;
    }
    fib(5)

    直接调用一个generator和调用函数不一样,fib(5)仅仅是创建了一个generator对象,还没有去执行它,它只是返回一个遍历器对象(Iterator Object)。

    调用generator对象有两个方法,一是不断地调用generator对象的next()方法:

    var f = fib(5);
    f.next(); // {value: 0, done: false}
    f.next(); // {value: 1, done: false}
    f.next(); // {value: 1, done: false}
    f.next(); // {value: 2, done: false}
    f.next(); // {value: 3, done: false}
    f.next(); // {value: undefined, done: true} 如果继续调用next方法,返回的也都是这个值

    next()方法会执行generator的代码,然后,每次遇到yield x;就返回一个对象{value: x, done: true/false},然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。如果donetrue,则value就是return的返回值。当执行到donetrue时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。

    第二个方法是直接用for ... of循环迭代generator对象,这种方式不需要我们自己判断done

    for (var x of fib(10)) {
        console.log(x); // 依次输出0, 1, 1, 2, 3, ...
    }

    yield 表达式如果用在另一个表达式中,必须放在圆括号里面:

    {
      function* demo() {
        console.log('Hello' + yield); // SyntaxError
        console.log('Hello' + yield 123); // SyntaxError
      
        console.log('Hello' + (yield)); // OK
        console.log('Hello' + (yield 123)); // OK
      }
    }

    yield 表达式用作参数或放在赋值表达式的右边,可以不加括号:

    {
      function* demo() {
        foo(yield 'a', yield 'b'); // OK
        let input = yield; // OK
      }
    }

    如果在 Generator 函数里面调用另一个 Generator 函数,默认情况下是没有效果的:

    {
      function* foo() {
        yield 'aaa'
        yield 'bbb'
      }
    
      function* bar() {
        foo()
        yield 'ccc'
        yield 'ddd'
      }
    
      let iterator = bar()
    
      for(let value of iterator) {
        console.log(value)
      }
    
      // ccc
      // ddd
    
    }

    yield* 表达式用来在一个 Generator 函数里面 执行 另一个 Generator 函数:

    {
      function* foo() {
        yield 'aaa'
        yield 'bbb'
      }
    
      function* bar() {
        yield* foo()      // 在bar函数中 **执行** foo函数
        yield 'ccc'
        yield 'ddd'
      }
    
      let iterator = bar()
    
      for(let value of iterator) {
        console.log(value)
      }
    
      // aaa
      // bbb
      // ccc
      // ddd
    }

    抽奖每抽一次提示一次剩余次数:

    {
      // 具体抽奖逻辑的方法
      function draw(count) {
        // 执行一段抽奖逻辑
        // ...
    
        console.log(`剩余${count}次`)
      }
    
      // 执行抽奖的方法
      function* remain(count) {
        while(count > 0) {
          count--
          yield draw(count)
        }
      }
    
      let startDrawing = remain(6)
    
      let btn = document.createElement('button')
      btn.id = 'start'
      btn.textContent = '开始抽奖'
      document.body.appendChild(btn)
    
      document.getElementById('start').addEventListener('click', function(){
        startDrawing.next()
      }, false)
    }

    generator 函数实现轮询:

    {
      // 请求的方法
      function* ajax() {
        yield new Promise((resolve, reject) => {
          // 此处用一个定时器来模拟请求数据的耗时,并约定当返回的json中code为0表示有新数据更新
          setTimeout(() => {
            resolve({code: 0})
          }, 200)
        })
      }
    
      // 长轮询的方法
      function update() {
        let promise = ajax().next().value    // 返回的对象的value属性是一个 Promise 实例对象
        promise.then(res => {
          if(res.code != 0) {
            setTimeout(() => {
              console.log('2秒后继续查询.....')
              update()
            }, 2000)
          } else{
            console.log(res)
          }
        })
      }
    
      update()
    }

    转载:https://www.liaoxuefeng.com/wiki/1022910821149312/1023024381818112

               https://my.oschina.net/pandon/blog/750333

               https://www.cnblogs.com/rogerwu/p/10764046.html

  • 相关阅读:
    git操作
    计算天数
    web小结~2019.3.24
    数据统计值的计算+PYTHON
    python~序列类型及操作
    一个日期加上若干天后是什么日期
    完数与盈数
    分段函数
    求最大最小
    D进制的A+B
  • 原文地址:https://www.cnblogs.com/xjy20170907/p/11414524.html
Copyright © 2011-2022 走看看