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

onClick触发Fetch API在Safari报错Load failed问题排查

问题描述

我并非前端方向开发人员,遇到了一个基础的HTML/JavaScript问题,希望得到帮助。

实现需求

朋友的网站基于Wordpress搭建、使用Thrive主题,需要实现点击指定按钮时调用对应API的功能。Thrive主题支持在页脚注入自定义代码,我写了API调用函数,绑定到按钮对应的<a>标签的onclick事件上。
简化后的实现代码:

async function dummy() {
  var myHeaders = new Headers();
  myHeaders.append("Content-Type", "text/plain");

  var requestOptions = {
    method: "POST",
    headers: myHeaders,
    body: JSON.stringify({}),
    redirect: "follow",
  };

  return fetch("some.api.com", requestOptions);
}

document.getElementById("button1").onclick = async function () {
  var res = await dummy();
  return res.ok;
};

故障现象

代码在Chrome浏览器可正常运行,但在Safari及移动端浏览器中运行异常,多数场景下Safari会抛出错误:Unhandled Promise Rejection: TypeError: Load failed。调整过await写法后偶尔能运行成功,但始终无法稳定工作。

注:我清楚当前写法不符合生产环境安全标准,仅为演示场景的快速实现。


故障原因与修复方案

代码存在4个直接导致Safari下运行不稳定的问题,按影响优先级排序:

  • 未阻止<a>标签的默认跳转行为
    这是最核心的原因。你绑定点击事件的是a标签,async类型的事件回调执行到await时会暂时让出主线程,Safari会在此时立刻触发a标签的默认行为:如果href是#或空值就触发页面刷新/锚点跳转,如果是其他地址就直接跳走。页面上下文一旦被销毁,还在等待响应的fetch请求会被直接中断,抛出Load failed错误。Chrome对这类场景做了特殊容错,不会立刻销毁上下文中断请求,但Safari、iOS端所有浏览器(包括iOS Chrome、微信Webview)都没有这个容错,因此会大概率失败。
  • 请求URL缺少协议前缀
    代码里的接口地址写的是some.api.com,没有带https://协议头,Safari不会像Chrome那样自动补全协议,会把该地址识别为当前站点下的相对路径,往Wordpress站点自身域名下拼接这个路径发请求,自然找不到目标接口。
  • 无异常捕获逻辑
    所有异步请求逻辑都没有加try/catch兜底,只要出现网络波动、请求被拦截、跨域校验失败的情况,就会直接抛出未处理的Promise拒绝错误。
  • Content-Type配置与请求体不匹配
    代码里设置的Content-Type是text/plain,但实际传的是JSON.stringify序列化后的JSON字符串,后端如果按JSON格式解析参数会直接失败,虽然这个问题不会直接触发前端Load failed报错,但会导致接口业务逻辑无法正常执行,应该改为application/json。

修正后可稳定运行的代码如下:

async function dummy() {
  const myHeaders = new Headers();
  // 修正Content-Type为JSON类型
  myHeaders.append("Content-Type", "application/json");

  const requestOptions = {
    method: "POST",
    headers: myHeaders,
    body: JSON.stringify({}),
    redirect: "follow",
  };
  // 补全接口完整协议头,替换为实际接口的全路径地址
  return fetch("https://some.api.com/your-actual-api-path", requestOptions);
}

document.getElementById("button1").onclick = async function (e) {
  // 阻止a标签默认跳转行为
  e.preventDefault();
  try {
    const res = await dummy();
    // 此处可添加请求成功后的业务逻辑,比如弹出成功提示
    console.log("请求状态:", res.ok);
    return res.ok;
  } catch (err) {
    // 捕获所有请求异常,避免抛出未处理的Promise错误
    console.error("请求失败:", err);
    return false;
  }
};

如果调整后仍偶发失败,优先检查接口的CORS跨域配置:Safari对跨域规则的校验比Chrome严格很多,跨域响应头缺少Access-Control-Allow-Origin、Access-Control-Allow-Methods,或者携带Cookie时未配置Access-Control-Allow-Credentials,都会直接拦截请求抛出相同的Load failed错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:42:17