异步编程-Generator & async

Generator 基本用法

  • 在普通函数前面加上 * ,表示Generator函数
  • 在函数内,使用 yield关键词 暂停函数执行。可以向外抛出相关值,也可以接受函数外的值
  • 在函数外,使用 next()方法 启动Generator函数。遇到 yield关键词 时,可获取其值。也可以传递参数到函数内
  • 函数外可以抛出异常入函数内,函数内可使用 try…catch 捕获
console.log(`------------------------------\n----Generator基本用法\n------------------------------`)

// * 表示Generator函数
function* gener() {
    try {
        console.log("cernerator function")
        
        //遇到 yield关键词,函数执行暂停。有返回值,则向外抛出含有返回值的对象
        //同时,可以接受函数外的传值
        let outerData = yield "inner data"
        console.log(outerData) //outer data 
    } catch (error) {
        console.log(error)
    }
}

//调用Generator函数,只是返回Generator对象,并不是执行其代码
let generator = gener()
console.log(generator) // gener {<suspended>}

//调用next()方法,才是启动执行Generator函数的内部代码
//可以接受Generator函数内部的返回值
//返回对象中的 done 是指函数是否执行完成
let innerData = generator.next()
console.log(innerData) //{value: "inner data", done: false}

//再次启动Generator函数,可以传递值
generator.next("outer data")

//手动抛个异常
generator.throw(new Error("outer error"))

Generator 与 Promise结合调用

* 可以依次调用多个接口
* 将Promise的异步操作,通过Generator组装为近似同步的操作
(users.json)

[
    {
        "name": "asd",
        "age": 32
    },
    {
        "name": "bbb",
        "age": 12
    }
]

(classes.json)

[
    {
        "className": "A1班",
        "level": "三年级"
    },
    {
        "className": "A5班",
        "level": "二年级"
    }
]

(js)

console.log(`------------------------------\n----Generator 与 Promise结合调用\n------------------------------`)

//请求函数
const ajax = function (url) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status == 200) {
                resolve(this.response)
            } else {
                reject(this.statusText)
            }
        }
        xhr.send();
    })
}

//Generator函数
function* main() {

    //请求classes.json数据,并返回包含Promise的对象,且暂停函数
    let className = yield ajax("/api/classes.json")
    console.log("className:", className) //className: A1班
    
    //请求users.json数据,并返回包含Promise的对象,且暂停函数
    let userName = yield ajax("/api/users.json")
    console.log("userName:", userName)
}

//调用Generator函数,并启用Generator函数
let generator = main()
let classGenerator = generator.next()
console.log("classGenerator:", classGenerator) //classGenerator: {value: Promise, done: false}

//检查Generator函数是否完成
if (classGenerator.done) return
let classPromise = classGenerator.value//获取Promise对象

//获取ajax请求到数据
classPromise.then(res => {
    let className = res[0].className
    
    //拿到数据后,再次启动Generator函数,并将所需参数传递到Generator函数内容
    //获取到下一个yield所在的ajax调用,并返回包含该调用的Promise的Generator对象
    let userGenerator = generator.next(className)
    console.log("userGenerator:", userGenerator) //userGenerator: {value: Promise, done: false}
    
    //检查Generator函数是否完成
    if (classGenerator.done) return
    let userPromise = userGenerator.value
    
    userPromise.then(userRes => {
        let userName = userRes[0].name
        console.log(userName)
        //如果还有其他的调用,则继续...
    })
})

Generator的执行器

  • 利用递归的方法,简化上面的代码
    (users.json)
[
    {
        "name": "asd",
        "age": 32
    },
    {
        "name": "bbb",
        "age": 12
    }
]

(classes.json)

[
    {
        "className": "A1班",
        "level": "三年级"
    },
    {
        "className": "A5班",
        "level": "二年级"
    }
]

(js)

console.log(`------------------------------\n----Generator的执行器\n------------------------------`)

//请求函数
const ajax = function (url) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status == 200) {
                resolve(this.response)
            } else {
                reject(this.statusText)
            }
        }
        xhr.send();
    })
}

//需调用接口的函数
function* generatorFn() {
   try {
        console.log("generator")
        
        let users = yield ajax("/api/users.json")
        console.log("generator users:", users) //generator users: (2) [{…}, {…}]
        
        let classes = yield ajax("/api/classes.json")
        console.log("generator classes:", classes) //generator classes: (2) [{…}, {…}]
        
        //异常处
        let errorTest = yield ajax("/api/error-path.json")
        console.log("generator errorTest:", errorTest)
        
    } catch (error) {
        console.log(error)
    }
}

//Generator的执行器
function co(generatorFn) {

    const generator = generatorFn()
    
    //递归方法
    function handleResult(result) {
    
        if (result.done) return//Generator函数执行结束,则停止递归
        
        result.value.then(res => {
            //启动Generator函数,并递归
            handleResult(generator.next(res))
        })
            .catch(err => {//使用catch捕获异常
                generator.throw(err)
            })
    }
    
    //使用Generator函数,只需启用一次
    handleResult(generator.next())
}

//使用执行器
co(generatorFn)

async 和 await 语法糖

  • 与 * 和 yield 的使用差不多
  • 不需要执行器,直接调用即可
  • await只会出现在async修饰的函数内部
    (简化上述代码)
console.log(`------------------------------\n----async和await语法糖\n------------------------------`)

//请求函数
const ajax = function (url) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status == 200) {
                resolve(this.response)
            } else {
                reject(this.statusText)
            }
        }
        xhr.send();
    })
}

//需调用接口的函数
//将 * 换成 async
//将 yield 换成 await
async function generatorFn() {
    console.log("generator")
    
    let users = await ajax("/api/users.json")
    console.log("generator users:", users) //generator users: (2) [{…}, {…}]
    
    let classes = await ajax("/api/classes.json")
    console.log("generator classes:", classes) //generator classes: (2) [{…}, {…}]
    
    //异常处
    let errorTest = await ajax("/api/error-path.json")
    console.log("generator errorTest:", errorTest)
}

//直接调用Generator函数即可
//不需要执行器,因为它是语言层面的,标准异步编程语法
//返回一个Promise的对象
generatorFn().then(res => {
    console.log("all complete!")
}).catch(err => {
    console.log(err)
})
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值