You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native+ApolloJS:如何并行发送多个GraphQL请求(无await串行)

环境依赖

{
  "@apollo/client": "^3.6.8",
  "apollo-link-logger": "^2.0.0",
  "apollo-link-token-refresh": "^0.4.0",
  "graphql": "^16.5.0",
  "graphql-tag": "^2.11.0",
  "react": "17.0.2",
  "react-native": "=0.68.0"
}

问题描述

当前在React.FC中通过await串行调用Apollo Client请求,代码如下:

const loadData = async() => {
    await wait(800);
    await dataService1.getData1();
    await dataService1.getData2();
    await dataService1.getData3();
    await dataService1.getData4();
    await dataService1.getData5();
    await dataService2.getData6();
    await dataService3.getData7()
    setLoading(false);
};

该方式可正常运行,但加载耗时超11秒,速度过慢。尝试移除await并行触发请求时,Apollo未发送全部请求,部分请求直接丢失。

每个请求都会触发中间件链中的拦截器(用于添加认证Bearer token),怀疑问题出在中间件链末端的httpLink,Apollo Client配置如下:

// Constructor of ApolloClientService
this.httpLink = createHttpLink({
    uri: `https://${this.api}/graphql`,
});

// this.httpLink = new BatchHttpLink({ uri: `https://${this.api}/graphql`});

this.link = split(({ query }) => {
    const {
        kind,
        operation,
    }: {
        kind: string;
        operation?: string;
    } = getMainDefinition(query);
    return kind === 'OperationDefinition' && operation === 'subscription';
}, this.httpLink);

this.defaultOptions = {
    watchQuery: {
        fetchPolicy: 'no-cache',
        errorPolicy: 'ignore',
    },
    query: {
        fetchPolicy: 'no-cache',
        errorPolicy: 'all',
    },
    mutate: {
        // errorPolicy: 'all',
    },
};

this.client = new ApolloClient<NormalizedCacheObject>({
    link: ApolloLink.from([
        onError(this.handleError),
        setContext(this.interceptRequest),
        apolloLogger,
        this.httpLink,
    ]),
    cache: new InMemoryCache(),
    defaultOptions: this.defaultOptions,
    connectToDevTools: false,
    queryDeduplication: false,
});

限制条件:无法使用BatchLink(服务器不支持且暂无重构时间)、Apollo Hooks(useQuery/useMutation)或Apollo React组件方案,需要实现像REST API那样并行发送多个独立的GraphQL请求。


解决方案

1. 使用Promise.all实现并行请求

Apollo Client本身支持并行发送请求,直接移除await导致请求丢失的原因是未正确管理Promise生命周期。用Promise.all包裹所有请求Promise,可确保所有请求同时发起并等待全部完成:

const loadData = async() => {
    await wait(800);
    // 收集所有请求Promise,并行触发
    const requestPromises = [
        dataService1.getData1(),
        dataService1.getData2(),
        dataService1.getData3(),
        dataService1.getData4(),
        dataService1.getData5(),
        dataService2.getData6(),
        dataService3.getData7()
    ];
    // 等待所有请求执行完成
    await Promise.all(requestPromises);
    setLoading(false);
};

2. 排查请求丢失的潜在原因

如果使用Promise.all后仍有请求丢失,需检查以下几点:

  • 拦截器线程安全:确保interceptRequest是无状态纯函数,每次调用返回独立的上下文对象,避免并行请求共享状态导致参数覆盖:
    const interceptRequest = async (operation, context) => {
        const token = await getCurrentToken(); // 从安全存储(如AsyncStorage)获取token
        return {
            ...context,
            headers: {
                ...context.headers,
                Authorization: token ? `Bearer ${token}` : '',
            },
        };
    };
    
  • 错误处理链路:检查onError拦截器是否中断了请求链路,确保即使单个请求报错,也不影响其他并行请求:
    const handleError = ({ graphQLErrors, networkError, operation, forward }) => {
        if (graphQLErrors) {
            graphQLErrors.forEach(({ message, locations, path }) =>
                console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`)
            );
        }
        if (networkError) console.log(`[Network error]: ${networkError}`);
        // 返回forward(operation)确保链路继续执行
        return forward(operation);
    };
    
  • React Native网络并发限制:React Native默认限制并发网络请求数(通常为6个),超过的请求会排队而非丢失。若请求数量较多,可分组并行执行:
    const loadData = async() => {
        await wait(800);
        // 分批次并行请求
        const batch1 = [dataService1.getData1(), dataService1.getData2(), dataService1.getData3()];
        const batch2 = [dataService1.getData4(), dataService1.getData5(), dataService2.getData6()];
        const batch3 = [dataService3.getData7()];
        
        await Promise.all(batch1);
        await Promise.all(batch2);
        await Promise.all(batch3);
        
        setLoading(false);
    };
    

内容的提问来源于stack exchange,提问作者idRem7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:55:17