如何在异步函数中正确使用await处理GraphQL异步数据请求?
关于异步函数调用中
await的用法与最佳实践 核心结论:当前写法无需await,且更高效
你现在的fetchSomeData写法完全合理——不需要加await。因为fetchGraphQLData本身返回一个Promise,而async函数会自动将返回的非Promise值包装成Promise,直接返回这个Promise和用await接收后再返回效果完全等价,但少了一层不必要的Promise解析步骤,性能更优。
两种写法对比:
// 当前推荐写法 const fetchSomeData = async (): Promise<TQueryResult<TSomeData>> => { return fetchGraphQLData<TSomeData>({ query: someQuery }); }; // 等价但冗余的写法 const fetchSomeData = async (): Promise<TQueryResult<TSomeData>> => { const result = await fetchGraphQLData<TSomeData>({ query: someQuery }); return result; };
什么时候需要加await?
只有当你需要在返回结果前对fetchGraphQLData的返回值做额外处理时,才需要用await拿到具体数据:
const fetchSomeData = async (): Promise<TQueryResult<TSomeData>> => { const result = await fetchGraphQLData<TSomeData>({ query: someQuery }); // 示例:修改数据格式、过滤无效值 if (result.data) { result.data = transformRawData(result.data); } return result; };
潜在陷阱需注意
错误处理漏洞
当前fetchGraphQLData写法有风险:Apollo Client的query方法遇到网络错误或GraphQL错误时,默认会抛出异常,而非仅返回error字段。这意味着如果query失败,fetchGraphQLData会直接触发Promise的reject,不会返回包含error的对象。建议用try/catch包裹,确保错误被正确捕获并放入返回结构:export const fetchGraphQLData = async <T,>({ query, variables, }: QueryOptions): Promise<TQueryResult<T>> => { try { const { data, loading } = await getGraphQLClient().query<T>({ query, variables, }); return { data, loading, error: null }; } catch (err) { return { data: null, loading: false, error: err as Error }; } };重复创建Apollo Client实例
getGraphQLClient每次调用都会新建ApolloClient,这会导致缓存失效、资源浪费,严重影响性能。应该改成单例模式复用客户端:let client: ApolloClient<any> | null = null; const getGraphQLClient = (uri = DEFAULT_URI) => { if (!client) { const httpLink = createHttpLink({ uri }); client = new ApolloClient({ link: httpLink, cache: new InMemoryCache(), }); } return client; };类型定义一致性
确保TQueryResult的类型定义与fetchGraphQLData的返回结构完全匹配,避免类型不兼容问题。比如:type TQueryResult<T> = { data: T | null; loading: boolean; error: Error | null; };滥用
await的冗余开销
单个多余的await不会造成严重问题,但多层嵌套的不必要await会增加微任务队列的处理开销,尽量直接返回Promise简化执行流程。
内容的提问来源于stack exchange,提问作者username
相关产品推荐
相关产品推荐

