Skip to content

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

如有转载或 CV 的请标注本站原文地址