进阶学习7:JavaScript异步编程——Generator异步方案Async/ Await

Posted JIZQAQ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进阶学习7:JavaScript异步编程——Generator异步方案Async/ Await相关的知识,希望对你有一定的参考价值。

目录

六、Generator异步方案

1.前言

2.了解Generator的特点和基本使用

 3.使用Generator去实现异步

4.Async / Await语法糖


六、Generator异步方案

1.前言

前面学习到的链式调用Promise呢还是和我们同步模式不太一样,我们希望能够代码更加扁平化,而ES2015中提供的Generator就能解决这个问题

2.了解Generator的特点和基本使用

想解释的都写在下面代码的注释里拉。

//DEMO9
// 生成器函数回顾
// 比普通函数多了一个*号
function * foo () {
    console.log('start')
    try{
        const res = yield 'foo' // 函数内部可以随时使用yield返回一个值
        console.log(res)
    }
    catch (e) {
        console.log(e)
    }
    
}
const generator = foo()//不会立即执行函数,而是返回了一个Generator对象
console.log(generator)

const result = generator.next()//调用next()的时候才执行
//可以在接受.next()对象返回值这拿到yield返回的值,看console的结果里面还有一个done属性代表生成器是否全部执行完了
//yield不像return直接结束函数执行,只是暂停生成器执行
console.log(result)
//再次调用生成器.next()会从yield往后执行,给.next()中添加值的话,能让生成器函数yield获得一个接收值,也就是样例中res
const result2 = generator.next('bar')
console.log(result2)

//这里需要把上面两行注释掉,假如不注释的话生成器函数就已经结束了,生成器那是不会catch到Error的
generator.throw(new Error('Generator Error'))

结果:

注释掉这两行代码之后,再跑一次

const result2 = generator.next('bar')
console.log(result2)

结果:

 3.使用Generator去实现异步

//DEMO9
// 生成器函数 配合 Promise的异步方案
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)
    }
}

const g = main()
const result = g.next()
console.log(result.value)//返回的是promise
result.value.then(data => {
    const result2 = g.next(data)
    if(result2.done) return
    result2.value.then(data => {
        const result3 = g.next(data)
        if(result3.done) return
        result3.value.then(data =>
            g.next(data))
    })
})

结果:

这样确实是完成了我们想要做的,但是一层层的,代码实在是太丑了,完全可以使用递归来完成,下面就改造成递归,再增加异常捕获

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)
      const urls_error = yield ajax('/api/urls111.json')
      console.log(urls_error)
    } catch (e) {
      console.log(e)
    }
}

const g = main()
function handleResut(result) {
    if(!result.done){
        result.value.then(data => {
            const result2 = g.next(data)
            return handleResut(result2)
        }, error => {
            g.throw(error)
        })
    }else{
        return
    }
}

handleResut(g.next())

看一下运行结果,改造成功

4.Async / Await语法糖

ES2017中新增的,是语言层面的异步编程标准,使用起来更加方便一些(确实这个也是我自己在工作中使用最多的,实在是太方便了,代码阅读起来也容易)

//DEMO10
//ASYNC AWAIT
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')
})

返回结果: 

以上是关于进阶学习7:JavaScript异步编程——Generator异步方案Async/ Await的主要内容,如果未能解决你的问题,请参考以下文章

理解Javascript的异步

通过制作冰淇淋来学习 JavaScript 异步编程

JavaScript学习--Item27 异步编程异常解决方案

Web前端进阶之JavaScript模块化编程知识

《javascript高级程序设计》学习笔记 | 11.1.异步编程

Erlang 源码分析之 Gen_Server