You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获Adblocker导致的net::ERR_BLOCKED_BY_CLIENT错误,保障JS初始化?

解决广告拦截器导致$.getScript加载失败时.done回调不执行的问题

这个问题我之前处理过,广告拦截器触发的net::ERR_BLOCKED_BY_CLIENT错误确实会让jQuery的$.getScript和$.when组合陷入困境——默认情况下,这种网络级别的拦截不会被$.getScript的错误回调捕获,导致对应的Deferred一直处于pending状态,最终整个$.when的.done永远不会触发。

问题根源

$.getScript本质是$.ajax的简写,但它的错误处理逻辑对网络拦截类的错误支持不好。当请求被广告拦截器阻断时,浏览器不会返回标准的HTTP错误状态码,jQuery无法识别这种失败,也就不会触发Deferred的reject,导致$.when因为有一个pending的Deferred而无法进入done阶段。

解决方案:封装带可靠错误处理的脚本加载函数

我们可以自己封装一个safeGetScript函数,用原生$.ajax实现,确保任何加载失败(包括拦截)都能正确触发Deferred的状态变更,甚至可以让失败的请求也resolve,保证整体流程能继续执行。

步骤1:封装安全的脚本加载函数

function safeGetScript(url) {
  return $.ajax({
    url: url,
    dataType: "script",
    cache: true // 可选,开启脚本缓存提升性能,根据需求调整
  }).fail(function(xhr, status, error) {
    // 捕获所有加载失败情况,包括广告拦截器的阻断
    console.warn(`脚本加载失败: ${url}, 错误信息: ${error}`);
    // 关键:即使加载失败,也返回一个resolve的Deferred,保证整体流程不中断
    return $.Deferred().resolve();
  });
}

步骤2:替换原有代码中的$.getScript

把原来的$.getScript都换成我们封装的safeGetScript,这样每个脚本请求无论成功还是失败,都会让对应的Deferred进入resolved状态,$.when就能顺利触发.done回调:

$.when(
  safeGetScript("http://example.com/script1.js"),
  safeGetScript("http://example.com/script2.js"),
  safeGetScript("http://example.com/ads-script.js"),
  $.Deferred(function(deferred) { $(deferred.resolve); })
).done(function() {
  console.log('所有脚本请求已处理完成(含失败的广告脚本)');
  initialize();
});

进阶:区分成功/失败的脚本(可选)

如果你需要知道哪些脚本成功加载、哪些被拦截,可以修改safeGetScript返回状态标记,在.done中查看结果:

function safeGetScript(url) {
  return $.ajax({
    url: url,
    dataType: "script",
    cache: true
  }).then(
    // 成功时返回true
    () => ({ url, success: true }),
    // 失败时返回false和错误信息
    (xhr, status, error) => {
      console.warn(`脚本加载失败: ${url}, 错误信息: ${error}`);
      return { url, success: false, error };
    }
  );
}

// 批量处理脚本请求
const scriptUrls = [
  "http://example.com/script1.js",
  "http://example.com/script2.js",
  "http://example.com/ads-script.js"
];
const deferreds = scriptUrls.map(url => safeGetScript(url));
// 加上DOM ready的Deferred
deferreds.push($.Deferred(deferred => $(deferred.resolve)));

$.when.apply($, deferreds).done(function(...results) {
  console.log('所有脚本请求处理完成:', results);
  // 可以在这里过滤成功/失败的脚本
  const failedScripts = results.filter(res => res?.success === false);
  if (failedScripts.length > 0) {
    console.log('被拦截或加载失败的脚本:', failedScripts.map(res => res.url));
  }
  initialize();
});

为什么原来的fail/error回调无效?

因为$.getScript的错误回调只处理HTTP级别的错误(比如404、500),而广告拦截器的net::ERR_BLOCKED_BY_CLIENT属于浏览器层面的网络拦截,不会触发jQuery默认的错误处理逻辑。改用$.ajax后,我们能捕获到更底层的错误事件,确保Deferred状态正确更新。

内容的提问来源于stack exchange,提问作者Billy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:26:02