likes
comments
collection
share

深入理解 ES6 的异步编程:Generator 函数、Promise 与 Thunk

作者站长头像
站长
· 阅读数 71

本章主题: 深入了解 ES6 generator 函数 | Promise | Thunk

本章介绍了 ES6 中的 Generator 函数、Promise 和 Thunk,通过实例代码详细讲解了它们的定义和用法。重点展示了 Generator 与 Promise 结合实现异步操作的方法,以及递归封装异步控制流的实现,帮助读者掌握 ES6 异步编程技巧。

一、生成器函数 Generator Function

在 function 之后 , 函数名之前, 有一个 "*" 作为生成器函数的标示符。

function* gen(){
    yield 1; 
    yield 2;
}
const genx = gen() // 执行生成器, 返回一个生成器对象
// 启动生成器
genx.next();
genx.next();

const obj = {
    key1: 'val1',
    key2: 'val2',
    [Symbol.iterator]: function(){
    
        return {
            next: function(){
                return {value: 'xxx', done: false}
            }
        }
    }
}
// generator 函数版本
const obj = {
    key1: 'val1',
    key2: 'val2',
    [Symbol.iterator]: function*() {
        yield obj.key1;
        yield obj.key2;
    }
}

yield: 切出当前函数的运行时, 类协程 Semi-coroutine, 与此同时, 可以将一个值带入到主线程中。

next | throw | Symbol.iterator

单步调试的流程

生成器数组解构

const [a,b,c,d,e,f,g] = genx()

函数外向函数内通信

function* demo(){
    const val1 = yield 1;
    console.log(val1)
    const val2 = yield 2;
    console.log(val1)
    return 3
}
const gen = demo()

const step1 = gen.next()
const step2 = gen.next("a") // 上一个 yield 会被 参数替代
const step3 = gen.next("b")

深入理解 ES6 的异步编程:Generator 函数、Promise 与 Thunk

yield 等待 Promise Fullfilled , 执行完成后将结果给 data

yield Promise

以近似同步的写法使用异步方法

await 本质是 generator 的语法糖

function get(str){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(10)
        },100)
    })
}
function* fetchDemo(){
    const data = yield get("/xxx") // data => 10
    console.log(data)
    const data2 = yield get("/yyy")
    console.log(data2)
    const data3 = yield get("/zzz")
    console.log(data3)
}
const gen = fetchDemo()
const step1 = gen.next()  // {value: Promise<pending>, done: false}
const step2 = gen.next("a") 
const step3 = gen.next("b")
const step4 = gen.next("c")
console.log(step1,step2,step3,step4)

异步控制流语法

function get(str){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(Date().now)
        },100)
    })
}
function* fetchDemo(){
    const data = yield get("/xxx") // data => 10
    console.log(data)
    const data2 = yield get("/yyy")
    console.log(data2)
    const data3 = yield get("/zzz")
    console.log(data3)
}
// const gen = fetchDemo()
// const step1 = gen.next()
// const step2 = gen.next("a")
// const step3 = gen.next("b")
// const step4 = gen.next("c")

// const result = gen.next() //{value: Promise{<pending>}, done: false}


// 如何包装这一块代码
const step1 = gen.next()
step1.value.then(data => {
    const step2 = gen.next(data)
    step2.value.then(data=>{
        const step3 = gen.next(data)
        step3.value.then(data=>{
            const step4 = gen.next(data)
        })
    })
})

console.log(step1,step2,step3,step4)

通过递归封装

// 期望 run(fetchDemo) => 执行全部 yield
// 通过递归封装
function run(generator){
    const iterator = generator()
    function step(data){
        const result = iterator.next(data)
        if(result.done){
            return result.value
        }
        result.value.then(data=>{
            step(data)
        })
    }
    step()
}
run(fetchDemo)

generator 函数实现了异步控制流, 实际等待异步函数的时间, 在 generator 函数内还是函数外。

async / await 的原理

* 改成 async 
yield 改成 await 
再加一个自动执行器

深入理解 ES6 的异步编程:Generator 函数、Promise 与 Thunk

二、Promise

Promise 基本语法

new Promise((resolve, reject) => {
    setTimeout(()=>{
        resolve("OK")
    },1000)
})

Promise 的三种状态 pending fullfilled rejected

Promise 的构造函数执行是同步的

Promise.then 的两个参数 fullfilled & rejected

Promise.catch 等价于 Promise.then(null, (err)=> console.log(err))

Promise.finally 等价于 Promise.then(()=> console.log('finally'), ()=> console.log('finally'))

Promise.resolve('foo') 等价于 new Promise(resolve => resolve('foo'))

Promise.resolve() 的参数四种类型 romise 实例 | thenable 对象 | 参数不是具有 then() 方法的对象,或根本就不是对象 | 不带有任何参数

const p = Promise.reject('出错了') 等同于 const p = new Promise((resolve, reject) => reject('出错了'))

Promise.all | Promise.race | Promise.any | Promise.allSettled

function get(str){
    return new Promise((resolve)=>{
        console.log("请求了:", str)
        setTimout(()=>{
            resolve(Date.now())
        },1000)
    })
}
get("/xxx").then(data => data + 1)
.then(data2 => get('/yyy'))
.then(data3 =>{
    console.log(data3) // 请问 data3 的数据类型是什么? resolve 的值
})

// 相当于
.then(data2 => get('/yyy').then(data3 =>{console.log(data3)}))

参考网站: es6.ruanyifeng.com/ #docs/promise

三、Thunk 函数

es6.ruanyifeng.com/#docs/generator-async#Thunk-%E5%87%BD%E6%95%B0

emitter checker binder scanner

拓展

  • async/await 是 generator 函数的语法糖。
  • new Promise 中的 setTimeout 不需要 clear 么?
  • Promise | Generator | 异步控制流 核心。
转载自:https://juejin.cn/post/7379059228105195572
评论
请登录