学习笔记 JavaScript ES6 异步编程Grenerator用法

  • Grenerator的语法和普通的函数是完全不同的,Grenerator在执行时可以暂停,然后可以在暂停的位置继续执行。就是一步一步的执行。
  • 不能做为构造函数使用,只能返回一个生成器对象
  • Grenerator函数的特点是function后面有一个“ * ”号,一般function和*紧挨在一起。

通过下面的输出可以看到,仅返回了一个Generator函数,而且for循环没有被执行,这是因为gererator函数需要手动执行

// 一般function和*紧挨在一起
function* foo(params) {
  for (let i = 0; i < 3; i++) {
    console.log(i);
    yield i; // 生产或产出i
  }
}
console.log(foo());

---------------------------
Generator {_invoke: ƒ}

再来看,下面代码中.next()是固定的语法,输出的是一个对象,对象有两个属性,一个是value,一个是done。value代表当前值是什么,done表示Generator函数是否执行完。

// 一般function和*紧挨在一起
function* foo(params) {
  for (let i = 0; i < 3; i++) {
    
    // 生产或产出i
    yield i;
  }
}

// next()是固定的语法
let f = foo().next()
console.log(f);

-------------------------------
{value: 0, done: false}

再继续看,当调用next()后,会执行到yield后面的语句为止,再次调用时,会从当前yield语句之后执行

// 一般function和*紧挨在一起
function* foo(params) {
  for (let i = 0; i < 3; i++) {
    // console.log(i);
    yield i;
  }
}

// next()是固定的语法
let f = foo()
console.log(f.next());
console.log(f.next());
console.log(f.next());
console.log(f.next());

------------------------------------
{value: 0, done: false}
{value: 1, done: false}
{value: 2, done: false}
{value: undefined, done: true}

yield只能在Generator内部使用,不能在其它地方用,比如下面不能在其它函数里使用:

function gen(params) {
    params.forEach(item => {
        yield item 
    });
}

----------------------
Module build failed 

来看一个复杂一点的例子:

next()可以传一个参数,这个参数表示的是Grenerator内部的上一条yield语句的返回值

function* gen(x) {
  let y = 2 * (yield x + 1);
  let z = yield y / 3;
  return x + y + z;
}
let g = gen(5)
console.log(g.next()) // x + 1 = 6
// 这里没有传参,相当于传入的是undefined
console.log(g.next()) // 2 * undefined = NaN
console.log(g.next()) // NaN

----------------------------------
{value: 6, done: false}
{value: NaN, done: false}
{value: NaN, done: true}

现在把参数都传进去试一下:

function* gen(x) {
  let y = 2 * (yield x + 1);
  let z = yield y / 3;
  return x + y + z;
}
let g = gen(5)
console.log(g.next())
console.log(g.next(12))
console.log(g.next(13))

// ------------------------------
{value: 6, done: false}
{value: 8, done: false}
{value: 42, done: true}

小例子7的倍数就暂定 

function* count(x = 1) {
    while (true) {
        if( x % 7 === 0) {
            yield x
        }
        x++
    }
}
let n = count()
console.log(n.next().value)
console.log(n.next().value)
console.log(n.next().value)
console.log(n.next().value)

--------
7
14
21
28

再来看把之前Promise()里的三个异步请求改造到Grenerator函数中:

再次理解next(),next会执行到yield后面的表达式,这个不要忘记了

function ajax(url, callback) {
    var xmlhttp;
    // 1、创建XMLHttpRequest对象
    // window.XMLHttpRequest这个对象存在,说明当前浏览器是IE7+或chrome
    if (window.XMLHttpRequest) {
      xmlhttp = new XMLHttpRequest();
    } else {
      // 兼容早期浏览器
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
  
    // 2、发送请求
    xmlhttp.open("GET", url, true);
    xmlhttp.send();
  
    // 3、接收服务端响应
    xmlhttp.onreadystatechange = function () {
      if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
        var obj = JSON.parse(xmlhttp.responseText);
        callback(obj)
      }
    };
  }
  
  var addUrl = "http://jsonplaceholder.typicode.com/users";
  
  function request(url) {
    ajax(url, res => {
        getData.next(res);
    })    
  }
 
  function* gen() {
      let res1 = yield request(addUrl)
      console.log(res1)
      let res2 = yield request(addUrl)
      console.log(res2)
      let res3 = yield request(addUrl)
      console.log(res3);
  }

  let getData = gen()
  getData.next();

--------------------------------------------------------------
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值