美文网首页程序员
Generator异步方案、AsyncAwait语法糖

Generator异步方案、AsyncAwait语法糖

作者: 翔子丶 | 来源:发表于2021-01-06 21:06 被阅读0次
    生成器函数(Generator)

    generator是一个函数,有两个特征:generatorfunction*定义,并且除了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/awaitgenerator的语法糖,将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)
      }
    }
    

    asyncPromisegenerator相比实现最简洁,最符合语义

    相关文章

      网友评论

        本文标题:Generator异步方案、AsyncAwait语法糖

        本文链接:https://www.haomeiwen.com/subject/lpbooktx.html