深入理解 ES6 的异步编程:Generator 函数、Promise 与 Thunk
本章主题: 深入了解 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")
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
再加一个自动执行器
二、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