ES2015的方案generator

通过一段代码回顾一下:

// 生成器函数回顾

function* foo() {
  console.log("start");

  try {
    const res = yield "foo";
    console.log(res);
  } catch (e) {
    console.log(e);
  }
}

// 生成器函数不会立即调用,而是返回一个generator对象
const generator = foo();

// 再使用其对象的next()方法之后才会调用生成器函数中的内容
// 并且在第一个yield关键字下停下
const result = generator.next();
// 也就是说下面这句话生成的值应该是foo
console.log(result);

// 这里接着使用next方法,其中带有的参数"bar"就会作为yield语句的返回值传递给res,然后执行到下一个yield
// generator.next('bar')

// 这里也会继续执行,抛出一个异常,走catch
generator.throw(new Error("Generator error"));

generator配合Promise的异步方案

递归执行generator函数

// Generator 配合 Promise 的异步方案

function ajax (url) {
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest()
    xhr.open('GET', url)
    xhr.responseType = 'json'
    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(xhr.response)
      } else {
        reject(new Error(xhr.statusText))
      }
    }
    xhr.send()
  })
}

function * main () {
  try {
    const users = yield ajax('/api/users.json')
    console.log(users)

    const posts = yield ajax('/api/posts.json')
    console.log(posts)

    const urls = yield ajax('/api/urls11.json')
    console.log(urls)
  } catch (e) {
    console.log(e)
  }
}

function co (generator) {
  const g = generator()

  function handleResult (result) {
    if (result.done) return // 生成器函数结束
    result.value.then(data => {
      handleResult(g.next(data))
    }, error => {
      g.throw(error)
    })
  }

  handleResult(g.next())
}

co(main)

其实生成器函数早在以前就有一个比较完善的库:
生成器函数CO

这个方案在2015年之前是比较流行的,因为语言有了await就不是很普及了,但是这个generator的作用和目的就是为了让异步编程回归扁平化,这在整个js发展过程中是非常重要的一步。

最后修改:2023 年 06 月 06 日
收款不要了,给孩子补充点点赞数吧