生成器函数(Generator)
generator
是一个函数,有两个特征:generator
由function*
定义,并且除了return
语句,还可以用yield
返回多次
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator(); // elloWorldGenerator {<suspended>}
直接调用Generator
函数,返回一个指向内部状态的指针对象;必须调用遍历器对象的next
方法,使指针状态移动
yeild
表达式暂停执行的标记,next
方法可以恢复执行
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false } // done属性为false 表示遍历没有完成
hw.next()
// { value: ending, done: true } // done属性为true 表示遍历已经完成
hw.next()
// { value: undefined, done: true }
-
generator
的异步方案const fetch = require('node-fetch') function* gen() { const url = 'https://es6.ruanyifeng.com/#docs/generator-async' const result = yield fetch(url) console.log(result) } const g = gen() const result = g.next() console.log(result) // { value: Promise { <pending> }, done: false } result.value.then((data) => data.size).then((data) => g.next(data))
Async/Await
函数
async
函数将generator
函数的星号(*)替换为async
,将yeild
替换为await
async
函数返回为Promise
对象,使用then
方法添加回调函数;函数执行一旦遇到await
就先返回,等待异步操作完成,再接着执行函数体内后面的语句
async/await
是generator
的语法糖,将generator
函数和自动执行器,包装在一个函数里
function co (generator) {
const g = generator()
function handleResult(result) {
if (result.down) return // 生成器函数结束
result.value.then(data = > {
// 递归调用直到执行完毕
handleResult(g.next(data))
}, error => g.throw(error))
}
handleResult(g.next())
}
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/urls.json')
console.log(urls)
} catch (e) {
console.log(e)
}
}
co(main)
async function main() {
try {
const users = await ajax('/api/users.json')
console.log(users)
const posts = await ajax('/api/posts.json')
console.log(posts)
const urls = await ajax('/api/urls.json')
console.log(urls)
} catch (e) {
console.log(e)
}
}
const promise = main()
promise.then(() => {
console.log('all completed')
})
使用注意:
-
await
命令后的Promise
对象,运行结果可能是reject
,最好将await
放在try...catch
中 -
多个
await
命令后的异步操作,如果不存在继发关系,最好同时触发let [foo, bar] = await Promise.all([getFoo(), getBar()])
-
await
命令只能用在async
中
function ajax(url) {
return new Promise((resolve, reject) => {
let 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()
})
}
async function main() {
try {
const users = await ajax('/api/users.json')
console.log(users)
const posts = await ajax('/api/posts.json')
console.log(posts)
const urls = await ajax('/api/urls.json')
console.log(urls)
} catch (e) {
console.log(e)
}
}
async
与Promise
、generator
相比实现最简洁,最符合语义
网友评论