Apollo Client循环中查询未等待完成问题排查求助
问题分析及修复方案
1. 冗余的Promise封装(核心问题)
Apollo Client的client.query本身就返回Promise,没必要手动包裹一层新的Promise。这种冗余封装不仅多余,还会导致错误无法被捕获——如果查询出现网络错误、GraphQL语法错误等,自定义Promise永远不会resolve或reject,可能引发代码卡死或异常行为。
2. 重复的Locale ID导致缓存触发
你的locales数组里所有项的id都是'fi',三次查询完全相同,Apollo Client默认的缓存策略会直接返回缓存结果,看起来像是“循环没等待”,实际是缓存加速了重复请求。这大概率是笔误,需要修正为对应语言的真实ID(比如瑞典语'sv'、英语'en')。
3. await与.then混合的冗余写法
fetchAllTranslations中同时使用await和.then,语法虽合法但可读性差,建议统一用await风格简化代码。
修复后的完整代码
import pkg from '@apollo/client' import * as fs from 'fs' const { ApolloClient, InMemoryCache, gql } = pkg const cmsUrl = 'HIDDEN' const client = new ApolloClient({ uri: cmsUrl, cache: new InMemoryCache(), }) // 修正locale的id为正确值 const locales = [ { name: 'finnish', id: 'fi', }, { name: 'swedish', id: 'sv', }, { name: 'english', id: 'en', }, ] // 去掉冗余Promise封装,直接返回query的Promise链 const fetchTranslations = async (locale) => { const result = await client.query({ query: gql` query GetTranslations($localeId: String!) { translations(first: 10000, locales: $localeId) { translation translationId locale } } `, // 使用GraphQL变量注入参数,避免字符串拼接风险 variables: { localeId: locale.id } }) return result.data.translations.reduce((acc, curr) => { acc[curr.translationId] = curr.translation return acc }, {}) } const fetchAllTranslations = async () => { try { for (const locale of locales) { console.log(`Fetching translations for ${locale.name}...`) // 统一用await替代.then,简化逻辑 const response = await fetchTranslations(locale) console.log(response) // 合并两次文件写入操作,减少IO开销 fs.writeFileSync(`src/translation/${locale.id}.json`, JSON.stringify(response)) } console.log('All translations are fetched') } catch (error) { // 统一捕获错误,避免程序崩溃 console.error('Fetch failed:', error) } } fetchAllTranslations()
额外优化说明
- 使用GraphQL变量注入参数,避免直接字符串拼接引发的语法错误和注入风险;
- 增加
try/catch统一捕获错误,方便排查查询或文件写入时的问题; - 合并重复的文件写入操作,减少不必要的磁盘IO。
内容的提问来源于stack exchange,提问作者Osmankaapa
相关产品推荐
相关产品推荐

