在循环中使用Promises时GraphQL请求回调未触发问题求解
问题根因
- JavaScript 是单线程事件驱动模型,同步任务的执行优先级远高于异步回调(包括 Promise 的 then/catch 回调)。你写的
while (true)是同步死循环,会一直占用主线程的执行权,永远不会让渡给事件循环去处理已经返回的请求回调。 - 当
requestCount涨到 5 之后,循环会一直走continue空转,既不会发新请求,也没有机会执行回调把requestCount减下来,程序就彻底卡住了。
修复方案
不要用同步死循环控制并发,可以采用「请求完成自动补位」的逻辑,始终维持最大并发数,完全不会阻塞主线程,异步回调也能正常执行:
import { request, gql } from 'graphql-request' const MAX_REQUESTS = 5; const countries = ['GB', 'UK', 'US', 'LT', 'IT', 'DE', 'MX'] const getRandomElement = (items) => { return items[Math.floor(Math.random()*items.length)]; } let activeRequests = 0; // 单个请求执行逻辑 async function runOneRequest() { activeRequests++ const country = getRandomElement(countries); const query = gql` { country(code: "${country}") { name native capital emoji currency languages { code name } } }` console.log('GET: ', country); try { const data = await request('https://countries.trevorblades.com/', query) console.log('OK: ', country); } catch (err) { console.log('FAILED: ', country); console.error(err) } finally { activeRequests-- // 完成一个请求后立刻启动下一个,始终维持最大并发数 runOneRequest() } } // 初始化启动最大并发数的请求 for (let i = 0; i < MAX_REQUESTS; i++) { runOneRequest() }
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

