导读:本期聚焦于小伙伴创作的《Tampermonkey中GM_xmlhttpRequest实现多链接并发请求与条件终止优化指南》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Tampermonkey中GM_xmlhttpRequest实现多链接并发请求与条件终止优化指南》有用,将其分享出去将是对创作者最好的鼓励。

Tampermonkey中GM_xmlhttpRequest实现多链接并发请求并条件终止

问题背景

在使用Tampermonkey编写用户脚本时,经常需要从多个URL获取数据。传统的顺序请求方式效率低下,而并发请求能显著提升性能。但有时我们需要在获取到符合条件的结果后立即停止其他正在进行的请求,避免不必要的网络开销。

解决方案概述

本文将介绍如何使用GM_xmlhttpRequest API实现以下功能:

  • 对多个链接发起并发请求
  • 监控每个请求的响应
  • 当某个请求返回符合条件的数据时,立即停止其他请求
  • 处理请求完成后的清理工作

核心实现思路

实现的关键在于维护一个请求状态管理器,记录所有请求的完成情况,并在满足终止条件时主动中止未完成的请求。

步骤分解

  1. 创建请求URL列表
  2. 初始化请求状态跟踪器
  3. 为每个URL发起GM_xmlhttpRequest
  4. 在响应回调中检查终止条件
  5. 满足条件时中止其他请求并执行回调
  6. 处理所有请求完成后的逻辑

完整代码实现

以下是实现多链接并发请求并条件终止的完整代码示例:

// ==UserScript==
// @name         多链接并发请求示例
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  演示如何使用GM_xmlhttpRequest实现多链接并发请求并在获取到符合条件的结果后停止后续请求
// @author       You
// @match        https://ippipp.com/*
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // 要请求的URL列表
    const urls = [
        'https://api.ipipp.com/data1',
        'https://api.ipipp.com/data2',
        'https://api.ipipp.com/data3',
        'https://api.ipipp.com/data4',
        'https://api.ipipp.com/data5'
    ];

    // 请求状态跟踪器
    const requestTracker = {
        completed: 0,
        total: urls.length,
        abortControllers: [],
        shouldAbort: false,
        successfulData: null
    };

    // 检查是否应该终止请求的条件函数
    function checkTerminationCondition(data) {
        // 这里定义你的终止条件,例如:
        // 1. 找到特定关键词
        // 2. 数据满足某种条件
        // 3. 响应状态码为特定值
        return data && data.status === 'success' && data.result && data.result.found;
    }

    // 中止所有未完成的请求
    function abortAllRequests() {
        requestTracker.abortControllers.forEach(controller => {
            if (controller && controller.abort) {
                controller.abort();
            }
        });
        requestTracker.abortControllers = [];
    }

    // 处理成功的响应
    function handleSuccess(response, url) {
        console.log(`请求成功: ${url}`, response);

        try {
            const data = JSON.parse(response.responseText);
            
            // 检查终止条件
            if (checkTerminationCondition(data)) {
                console.log('找到符合条件的结果,准备终止其他请求');
                requestTracker.shouldAbort = true;
                requestTracker.successfulData = data;
                
                // 中止其他请求
                abortAllRequests();
                
                // 执行成功回调
                onSuccessfulResult(data, url);
            }
        } catch (e) {
            console.error(`解析响应失败: ${url}`, e);
        }
    }

    // 处理失败的响应
    function handleError(error, url) {
        console.error(`请求失败: ${url}`, error);
    }

    // 请求完成回调
    function onRequestComplete(url) {
        requestTracker.completed++;
        console.log(`请求完成: ${url}, 进度: ${requestTracker.completed}/${requestTracker.total}`);

        // 检查是否所有请求都已完成
        if (requestTracker.completed >= requestTracker.total && !requestTracker.successfulData) {
            console.log('所有请求已完成,但未找到符合条件的结果');
            onAllRequestsCompleted();
        }
    }

    // 找到符合条件结果时的回调
    function onSuccessfulResult(data, url) {
        console.log('=== 找到符合条件的结果 ===');
        console.log('来源URL:', url);
        console.log('数据:', data);
        
        // 在这里处理你的业务逻辑
        // 例如:更新页面内容、显示通知等
        alert(`成功从 ${url} 获取到目标数据!`);
    }

    // 所有请求完成时的回调
    function onAllRequestsCompleted() {
        console.log('=== 所有请求已完成 ===');
        
        if (!requestTracker.successfulData) {
            console.log('未找到符合条件的结果');
            // 在这里处理未找到结果的业务逻辑
            alert('未找到符合条件的结果');
        }
    }

    // 发起单个请求
    function makeRequest(url, index) {
        // 创建中止控制器
        const abortController = { abort: () => {} };
        requestTracker.abortControllers[index] = abortController;

        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            timeout: 10000, // 10秒超时
            
            // 请求头
            headers: {
                'Content-Type': 'application/json',
                'User-Agent': 'Tampermonkey Script'
            },
            
            // 响应类型
            responseType: 'text',
            
            // 请求超时回调
            ontimeout: function(response) {
                handleError(new Error('请求超时'), url);
                onRequestComplete(url);
            },
            
            // 请求错误回调
            onerror: function(response) {
                handleError(new Error(`HTTP错误: ${response.status}`), url);
                onRequestComplete(url);
            },
            
            // 请求中止回调
            onabort: function(response) {
                console.log(`请求被中止: ${url}`);
                onRequestComplete(url);
            },
            
            // 请求成功回调
            onload: function(response) {
                // 检查响应状态
                if (response.status >= 200 && response.status < 300) {
                    handleSuccess(response, url);
                } else {
                    handleError(new Error(`HTTP状态码: ${response.status}`), url);
                }
                onRequestComplete(url);
            }
        });
    }

    // 主函数:发起所有请求
    function startConcurrentRequests() {
        console.log(`开始并发请求 ${urls.length} 个URL`);
        
        // 重置状态跟踪器
        requestTracker.completed = 0;
        requestTracker.total = urls.length;
        requestTracker.abortControllers = [];
        requestTracker.shouldAbort = false;
        requestTracker.successfulData = null;

        // 为每个URL发起请求
        urls.forEach((url, index) => {
            // 如果已经决定中止,不再发起新请求
            if (requestTracker.shouldAbort) {
                return;
            }
            makeRequest(url, index);
        });
    }

    // 启动请求
    startConcurrentRequests();

})();

代码详解

1. 请求状态跟踪器

requestTracker对象用于跟踪所有请求的状态:

  • completed: 已完成的请求数量
  • total: 总请求数量
  • abortControllers: 存储每个请求的中止控制器
  • shouldAbort: 标记是否需要中止其他请求
  • successfulData: 存储成功获取的数据

2. 条件检查函数

checkTerminationCondition函数是核心的条件判断逻辑,你可以根据实际需求修改这个函数:

function checkTerminationCondition(data) {
    // 示例条件:检查数据中是否包含特定字段
    return data && data.targetFound === true;
    
    // 其他可能的条件:
    // - 检查响应时间
    // - 验证数据完整性
    // - 匹配特定模式
}

3. 请求管理

makeRequest函数为每个URL创建独立的请求,并设置了完整的生命周期回调:

  • ontimeout: 处理请求超时
  • onerror: 处理网络错误和HTTP错误
  • onabort: 处理请求被中止的情况
  • onload: 处理成功响应

4. 并发控制

通过以下机制实现并发控制:

  • 同时发起所有请求,不等待前一个完成
  • 使用状态跟踪器监控整体进度
  • 条件满足时通过abortAllRequests中止所有未完成请求

关键注意事项

1. 跨域请求限制

GM_xmlhttpRequest不受同源策略限制,但仍需目标服务器允许跨域访问。如果遇到CORS问题,可能需要:

  • 在@connect指令中声明目标域名
  • 确保目标服务器支持CORS
  • 或使用JSONP等其他技术

2. 错误处理

完善的错误处理机制包括:

  • 网络超时处理
  • HTTP错误状态码处理
  • JSON解析错误处理
  • 中止操作的清理工作

3. 性能优化

为了提升性能,可以考虑:

  • 设置合理的超时时间
  • 限制最大并发数(如果需要)
  • 使用缓存避免重复请求
  • 压缩传输数据

4. 内存管理

及时清理资源:

  • 请求完成后移除中止控制器
  • 避免内存泄漏
  • 合理管理大型响应数据

扩展应用场景

这种模式适用于多种实际场景:

  • 多源数据聚合:从多个API获取相同数据,取最快返回的有效结果
  • 价格比较:同时从多个电商平台获取商品价格,找到最低价
  • 可用性检测:检查多个服务器的在线状态,找到第一个可用的
  • 内容搜索:在多个文档库中并行搜索,返回第一个匹配结果

总结

通过使用GM_xmlhttpRequest结合状态跟踪和条件检查机制,我们可以高效地实现多链接并发请求,并在获取到目标结果后立即终止其他请求。这种方法显著提升了数据获取效率,减少了不必要的网络开销。

在实际应用中,需要根据具体需求调整条件判断逻辑、错误处理策略和性能参数,以达到最佳效果。

Tampermonkey GM_xmlhttpRequest 并发请求 请求中止 脚本优化

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。