JavaScript 基于生成器的异步编程方案相关代码分享

基本的生成器

js 复制代码
// 定义生成器函数
function * foo(){
    console.log("start")
}

// 创建生成器
const generator = foo()

// 调用生成器
generator.next()

生成器的返回值

js 复制代码
// 定义生成器函数
function* foo() {
    console.log("start")

    // 通过 yield 返回内容
    yield "mara"
}

// 创建生成器
const generator = foo()

// 调用生成器
const result = generator.next()
console.log("result=", result)

生成器的参数

js 复制代码
// 定义生成器函数
function* foo() {
    console.log("start")

    // 通过 yield 返回内容
    const arg = yield "mara"
    console.log("arg = ", arg)
}

// 创建生成器
const generator = foo()

// 调用生成器
const result = generator.next()
console.log("result=", result)

// 再调用一次,才能执行到 yield 之后
generator.next("hello")

生成器结合 ajax 使用

js 复制代码
// 模拟 ajax 方法
function ajax(url) {
    return new Promise(function (resolve, reject) {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

// 定义生成器函数
function* userRequest() {
    const users = yield ajax("/users.json")
    console.log(users)
}

// 创建生成器
const generator = userRequest()

// 调用生成器
const result = generator.next()

// 进行处理
result.value.then(data => generator.next(data))

多个 ajax 请求

js 复制代码
// 模拟 ajax 方法
function ajax(url) {
    return new Promise(function (resolve, reject) {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

// 定义生成器函数
function* userRequest() {
    const users = yield ajax("/users.json")
    console.log(users)

    // 继续发请求
    const urls = yield ajax("/urls.json")
    console.log(urls)
}

// 创建生成器
const generator = userRequest()

// 调用生成器
let result = generator.next()

// 进行处理
result.value.then(data => {
    if (data.done) return

    result = generator.next(data)
    if (result.done) return;

    result.value.then(data=>{
        if (data.done) return
        generator.next()
    })
})

错误处理

js 复制代码
// 模拟 ajax 方法
function ajax(url) {
    return new Promise(function (resolve, reject) {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

// 定义生成器函数
function* userRequest() {
    const users = yield ajax("/users.json")
    console.log(users)

    // 继续发请求
    const urls = yield ajax("/urls.json")
    console.log(urls)

    // 发送一个错误的请求
    try{
        const mockError = yield ajax("/urls333.json")
        console.log("mockError", mockError)
    }catch (e){
        console.log("xxx", e)
    }
}

// 创建生成器
const generator = userRequest()

// 调度方法
function handleResult(result) {
    if (result.done) return
    result.value.then(data => {
        handleResult(generator.next(data))
    }).catch(err => generator.throw(err))
}

// 执行调度
handleResult(generator.next())

封装通用的执行器方法

js 复制代码
// 模拟 ajax 方法
function ajax(url) {
    return new Promise(function (resolve, reject) {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

// 定义生成器函数
function* userRequest() {
    const users = yield ajax("/users.json")
    console.log(users)

    // 继续发请求
    const urls = yield ajax("/urls.json")
    console.log(urls)

    // 发送一个错误的请求
    try{
        const mockError = yield ajax("/urls333.json")
        console.log("mockError", mockError)
    }catch (e){
        console.log("xxx", e)
    }
}

// 通用的执行器
function co(generator){
    // 创建生成器
    const g = generator()

    // 调度方法
    function handleResult(result) {
        if (result.done) return
        result.value.then(data => {
            handleResult(g.next(data))
        }).catch(err => g.throw(err))
    }

    // 执行调度
    handleResult(g.next())
}

// 调用通用的执行器
co(userRequest)

使用 async 和 await 语法糖

js 复制代码
// 模拟 ajax 方法
function ajax(url) {
    return new Promise(function (resolve, reject) {
        const xhr = new XMLHttpRequest()
        xhr.open("GET", url)
        xhr.responseType = "json"
        xhr.onload = function () {
            if (this.status === 200) {
                resolve(this.response)
            } else {
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

// 异步方法
async function userRequest() {
    const users = await ajax("/users.json")
    console.log(users)

    // 继续发请求
    const urls = await ajax("/urls.json")
    console.log(urls)

    // 发送一个错误的请求
    try {
        const mockError = await ajax("/urls333.json")
        console.log("mockError", mockError)
    } catch (e) {
        console.log("xxx", e)
    }
}


userRequest().then(resp => console.log(resp))
    .catch(error => console.log(error))
相关推荐
10年前端老司机29 分钟前
React 受控组件和非受控组件区别和使用场景
前端·javascript·react.js
夏晚星30 分钟前
vue实现微信聊天emoji表情
前端·javascript
極光未晚32 分钟前
TypeScript在前端项目中的那些事儿:不止于类型的守护者
前端·javascript·typescript
Rrvive34 分钟前
原型与原型链到底是什么?
javascript
xiangzhihong841 分钟前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
極光未晚1 小时前
JavaScript BOM 对象:浏览器的隐形控制塔
前端·javascript·源码
车载应用猿1 小时前
基于Android14的CarService 启动流程分析
android
天涯学馆1 小时前
网站秒变 App!手把手教你搞定 PWA
前端·javascript·面试
用户9272472502191 小时前
PHP + CSS + JS 数据采集与展示系统
javascript
没有了遇见2 小时前
Android 渐变色实现总结
android