Skip to content

使用 TanStack Query 优化 Console 端网络请求逻辑 #3360

@ruibaby

Description

@ruibaby

你当前使用的版本

2.2.1

描述一下此特性

目前 Console 端的所有请求均来自通过 OpenAPI Generator 生成的 api-client 来处理。但在某些业务场景下,需要手动处理的逻辑较多,比如自动重试、定时刷新、重复请求处理、加载状态、异常状态、分页、Suspense 等。 TanStack Query 可以非常容易地完成这些需求。

可以在新的业务模块中引入,旧的逻辑可以逐步修改。

/area console
/kind improvement

附加信息

例子:

在插件管理页面的简单尝试:

before:

const plugins = ref<PluginList>({
  page: 1,
  size: 20,
  total: 0,
  items: [],
  first: true,
  last: false,
  hasNext: false,
  hasPrevious: false,
  totalPages: 0,
});
const loading = ref(false);
const pluginInstall = ref(false);
const keyword = ref("");
const refreshInterval = ref();

const handleFetchPlugins = async (options?: {
  mute?: boolean;
  page?: number;
}) => {
  try {
    clearInterval(refreshInterval.value);

    if (!options?.mute) {
      loading.value = true;
    }

    if (options?.page) {
      plugins.value.page = options.page;
    }

    const { data } = await apiClient.plugin.listPlugins({
      page: plugins.value.page,
      size: plugins.value.size,
      keyword: keyword.value,
      enabled: selectedEnabledItem.value?.value,
      sort: [selectedSortItem.value?.value].filter(
        (item) => !!item
      ) as string[],
    });

    plugins.value = data;

    const deletedPlugins = plugins.value.items.filter(
      (plugin) => !!plugin.metadata.deletionTimestamp
    );

    if (deletedPlugins.length) {
      refreshInterval.value = setInterval(() => {
        handleFetchPlugins({ mute: true });
      }, 3000);
    }
  } catch (e) {
    console.error("Failed to fetch plugins", e);
  } finally {
    loading.value = false;
  }
};

onBeforeRouteLeave(() => {
  clearInterval(refreshInterval.value);
});

const handlePaginationChange = ({
  page,
  size,
}: {
  page: number;
  size: number;
}) => {
  plugins.value.page = page;
  plugins.value.size = size;
  handleFetchPlugins();
};

onMounted(handleFetchPlugins);

after:

const keyword = ref("");

const page = ref(1);
const size = ref(10);
const total = ref(0);

const selectedEnabledItem = ref<EnabledItem>();
const selectedSortItem = ref<SortItem>();

const {
  data: plugins,
  isLoading,
  isFetching,
  refetch,
} = useQuery<Plugin[]>({
  queryKey: [
    "plugins",
    page,
    size,
    keyword,
    selectedEnabledItem,
    selectedSortItem,
  ],
  queryFn: async () => {
    const { data } = await apiClient.plugin.listPlugins({
      page: page.value,
      size: size.value,
      keyword: keyword.value,
      enabled: selectedEnabledItem.value?.value,
      sort: [selectedSortItem.value?.value].filter(
        (item) => !!item
      ) as string[],
    });

    total.value = data.total;

    return data.items;
  },
  refetchOnWindowFocus: false,
  keepPreviousData: true,
  refetchInterval: (data) => {
    const deletedPlugins = data?.filter(
      (plugin) => !!plugin.metadata.deletionTimestamp
    );

    return deletedPlugins?.length ? 1000 : false;
  },
});

const handlePaginationChange = ({
  page: newPage,
  size: newSize,
}: {
  page: number;
  size: number;
}) => {
  // auto refresh
  page.value = newPage;
  size.value = newSize;
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/consoleIssues or PRs related to the Halo Consolekind/improvementCategorizes issue or PR as related to a improvement.priority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to complete.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions