[ahooks] useRequest源码阅读(二)

上一节我们分析了useRequest核心的Fetch模块的原理,这一节我们来看它是怎么使用的

useRequest

我们先来看useRequest这个hooks,可以看到它调用了useRequestImplement,并传入三个参数: service, optionsplugins,这里可以看到内部的plugins优先级要高于外部传入的:

ts 复制代码
import useAutoRunPlugin from './plugins/useAutoRunPlugin';
import useCachePlugin from './plugins/useCachePlugin';
import useDebouncePlugin from './plugins/useDebouncePlugin';
import useLoadingDelayPlugin from './plugins/useLoadingDelayPlugin';
import usePollingPlugin from './plugins/usePollingPlugin';
import useRefreshOnWindowFocusPlugin from './plugins/useRefreshOnWindowFocusPlugin';
import useRetryPlugin from './plugins/useRetryPlugin';
import useThrottlePlugin from './plugins/useThrottlePlugin';
import type { Options, Plugin, Service } from './types';
import useRequestImplement from './useRequestImplement';

function useRequest<TData, TParams extends any[]>(
  service: Service<TData, TParams>,
  options?: Options<TData, TParams>,
  plugins?: Plugin<TData, TParams>[],
) {
  return useRequestImplement<TData, TParams>(service, options, [
    ...(plugins || []),
    useDebouncePlugin,
    useLoadingDelayPlugin,
    usePollingPlugin,
    useRefreshOnWindowFocusPlugin,
    useThrottlePlugin,
    useAutoRunPlugin,
    useCachePlugin,
    useRetryPlugin,
  ] as Plugin<TData, TParams>[]);
}

export default useRequest;

useRequestImplement

先是对传入的参数进行默认值的赋值,生成fetchOptions,然后调用new Fetch()方法生成fetchInstance实例,这里可以看到紧接着就是运行所有插件获取插件的返回值,然后赋值给Fetch实例的pluginImpls属性:

ts 复制代码
const fetchInstance = useCreation(() => { 
    const initState = plugins.map((p) => p?.onInit?.(fetchOptions)).filter(Boolean); 
    // Generation Fetch Instance
    return new Fetch<TData, TParams>( serviceRef, fetchOptions, update, Object.assign({}, ...initState), ); 
}, []); 
fetchInstance.options = fetchOptions;
// run all plugins hooks 
fetchInstance.pluginImpls = plugins.map((p) => p(fetchInstance, fetchOptions));

接下来是判断初始化时是否自动执行一次,如果条件满足,则在组件挂载时执行初始化参数并调用实例的run 方法

在组件卸载时执行cancel方法

最后是组件返回包括data在内的各个state和方法

ts 复制代码
import useCreation from '../../useCreation';
import useLatest from '../../useLatest';
import useMemoizedFn from '../../useMemoizedFn';
import useMount from '../../useMount';
import useUnmount from '../../useUnmount';
import useUpdate from '../../useUpdate';
import isDev from '../../utils/isDev';

import Fetch from './Fetch';
import type { Options, Plugin, Result, Service } from './types';

function useRequestImplement<TData, TParams extends any[]>(
  service: Service<TData, TParams>,
  options: Options<TData, TParams> = {},
  plugins: Plugin<TData, TParams>[] = [],
) {
  const { manual = false, ready = true, ...rest } = options;

  if (isDev) {
    if (options.defaultParams && !Array.isArray(options.defaultParams)) {
      console.warn(`expected defaultParams is array, got ${typeof options.defaultParams}`);
    }
  }

  const fetchOptions = {
    manual,
    ready,
    ...rest,
  };

  const serviceRef = useLatest(service);

  const update = useUpdate();

  const fetchInstance = useCreation(() => {
    const initState = plugins.map((p) => p?.onInit?.(fetchOptions)).filter(Boolean);

    return new Fetch<TData, TParams>(
      serviceRef,
      fetchOptions,
      update,
      Object.assign({}, ...initState),
    );
  }, []);
  fetchInstance.options = fetchOptions;
  // run all plugins hooks
  fetchInstance.pluginImpls = plugins.map((p) => p(fetchInstance, fetchOptions));

  useMount(() => {
    if (!manual && ready) {
      // useCachePlugin can set fetchInstance.state.params from cache when init
      const params = fetchInstance.state.params || options.defaultParams || [];
      // @ts-ignore
      fetchInstance.run(...params);
    }
  });

  useUnmount(() => {
    fetchInstance.cancel();
  });

  return {
    loading: fetchInstance.state.loading,
    data: fetchInstance.state.data,
    error: fetchInstance.state.error,
    params: fetchInstance.state.params || [],
    cancel: useMemoizedFn(fetchInstance.cancel.bind(fetchInstance)),
    refresh: useMemoizedFn(fetchInstance.refresh.bind(fetchInstance)),
    refreshAsync: useMemoizedFn(fetchInstance.refreshAsync.bind(fetchInstance)),
    run: useMemoizedFn(fetchInstance.run.bind(fetchInstance)),
    runAsync: useMemoizedFn(fetchInstance.runAsync.bind(fetchInstance)),
    mutate: useMemoizedFn(fetchInstance.mutate.bind(fetchInstance)),
  } as Result<TData, TParams>;
}

export default useRequestImplement;

总结

至此useRequest的核心执行流程便分析完了,随后会不定时补出各个插件的源码分析,感谢各位的阅读

相关推荐
IT_陈寒37 分钟前
Redis大key删除引发的服务雪崩,这次我真记住了
前端·人工智能·后端
李少兄43 分钟前
深入解析 JavaScript 中的 `document` 对象
javascript
IMPYLH44 分钟前
HTML 的 <style> 元素
前端·html
paopaokaka_luck1 小时前
考研政治刷题小程序(AI推荐题目、ECharts数据分析、章节练习与专项训练、模拟考试、错题本与收藏夹、学习打卡与目标管理、题库和组卷维护)
前端·javascript·spring boot·spring·数据分析·echarts
刃神太酷啦1 小时前
前端入门第一课:HTML 基础语法 + 常用标签 + 实战全解
服务器·c语言·前端·javascript·css·c++·html
mldong1 小时前
给流程设计器加国际化,我没引 vue-i18n
前端·javascript·vue.js
IMPYLH1 小时前
HTML 的 <strong> 元素
前端·html
开开心心就好7 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
Setsuna_F_Seiei9 小时前
前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer(让 Agent 从全自动转变人为可掌控)
前端·agent·ai编程
百万蹄蹄向前冲11 小时前
风扇转了一晚上MVP专家团翻车事故
前端·人工智能