如何并行发起多链接GET请求并按序判断结果以终止后续请求
如何实现按请求返回顺序判断并终止剩余请求
需求与问题梳理
需求:同时发起多个GET请求,按请求结果返回的顺序逐个判断——第一个返回的结果符合条件则终止所有剩余请求;若不符合,继续判断下一个返回的结果,以此类推,直到找到符合条件的或所有请求完成。
原代码存在的问题:
- 仅通过
Promise.race获取第一个完成的请求,判断不符合后使用Promise.all等待所有请求完成再遍历,并非按返回顺序逐个判断 - 原Promise未封装取消能力,无法真正中止未完成的
GM_xmlhttpRequest请求 - 逻辑错误:第一个结果不符合时,没有继续按返回顺序处理后续完成的请求,而是等待全部完成后统一处理,不符合需求
解决方案
核心思路:同时发起所有请求,为每个请求封装取消能力,监听每个请求的完成事件,按返回顺序依次检查结果,一旦找到符合条件的,立即中止所有未完成的请求并停止后续判断。
实现代码
// 封装带取消能力的请求函数 function createRequestPromise(url) { let xhr; const promise = new Promise((resolve) => { xhr = GM_xmlhttpRequest({ method: "GET", url: url, onload: function(response) { try { const domNew = new DOMParser().parseFromString(response.responseText, 'text/html'); resolve({ data: domNew, url }); } catch (e) { resolve({ data: 'ERROR_PARSE', url }); } }, onerror: function(error) { resolve({ data: 'ERROR_REQUEST', url }); } }); }); // 添加cancel方法,用于中止请求 promise.cancel = () => { if (xhr && typeof xhr.abort === 'function') { xhr.abort(); } }; return promise; } // 请求链接列表 const urls = [ 'https://www.aaa.com', 'https://www.bbb.com', 'https://www.ccc.com' ]; // 生成所有请求Promise const requestPromises = urls.map(url => createRequestPromise(url)); let found = false; // 标记是否已找到符合条件的结果 // 监听每个请求的完成 requestPromises.forEach(promise => { promise.then(result => { if (found) return; // 已找到符合条件的,直接返回 const { data, url } = result; // 条件判断:区分错误结果与DOM对象的检查逻辑 const meetsCondition = typeof data === 'string' ? data.indexOf('#') > -1 : data.querySelector('#') !== null; if (meetsCondition) { found = true; console.log(`找到符合条件的结果,来自链接:${url}`, data); // 中止所有未完成的请求 requestPromises.forEach(p => p.cancel()); } else { console.log(`链接${url}不符合条件,继续等待...`); // 检查是否所有请求均已完成且未找到符合条件的 Promise.allSettled(requestPromises).then(results => { if (!found && results.every(r => r.status === 'fulfilled')) { console.log('所有请求均已完成,未找到符合条件的结果'); } }); } }); });
关键细节说明
- 请求封装:
createRequestPromise函数保存了GM_xmlhttpRequest的实例,并给Promise添加cancel方法,调用时执行xhr.abort()真正中止请求 - 顺序判断:每个请求完成后触发
then回调,通过found标志位避免重复处理,严格按返回顺序检查条件 - 中止逻辑:一旦找到符合条件的结果,立即调用所有未完成请求的
cancel方法,停止后续请求的处理 - 条件判断修正:原代码直接对DOM对象调用
indexOf('#')会报错,这里区分了字符串错误结果与DOM对象的检查逻辑,确保判断有效
内容的提问来源于stack exchange,提问作者lyscop
相关产品推荐
相关产品推荐

