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发展过程中是非常重要的一步。