useAsyncEffect
作用
一个让 useEffect 支持异步函数的 hook
原理
useEffect
的回调函数不支持异步函数,那么就在回调函数的内部执行异步函数即可。可以定义一个函数然后在执行这个函数。
源码
ts
import type { DependencyList } from 'react'
import { useEffect } from 'react'
// 判断是否是函数的工具方法
import { isFunction } from '../utils'
// 判断是否是异步生成器的工具方法
function isAsyncGenerator(
val: AsyncGenerator<void, void, void> | Promise<void>,
): val is AsyncGenerator<void, void, void> {
// Symbol.asyncIterator 符号指定了一个对象的默认异步迭代器。如果一个对象设置了这个属性,它就是异步可迭代对象,可用于for await...of循环。
return isFunction(val[Symbol.asyncIterator])
}
function useAsyncEffect(
// 异步回调函数
effect: () => AsyncGenerator<void, void, void> | Promise<void>,
// 依赖项
deps?: DependencyList,
) {
useEffect(() => {
const e = effect()
// 一个标识符,用于如果当前的effect被取消,yield会停止继续往下执行
let cancelled = false
// 定义可执行的异步函数
async function execute() {
// 如果是异步生成器,那么就执行异步生成器,通过next()方法来全部执行异步函数
if (isAsyncGenerator(e)) {
while (true) {
const result = await e.next()
// 如果异步生成器执行完毕或者effect被清理,那么就退出循环
if (result.done || cancelled) {
break
}
}
} else {
await e
}
}
execute()
return () => {
// 卸载的时候标记当前effect已经被清理
cancelled = true
}
}, deps)
}
export default useAsyncEffect