Safari 14中await request Promise失效,触发未处理Promise拒绝问题
解决Safari本地加载HTML文件的未处理Promise拒绝问题
问题根源
Safari处理file://协议的XMLHttpRequest请求时,成功加载本地文件后返回的xhr.status是0,而非Chrome中的200。你的request函数仅判断xhr.status >=200 && xhr.status <300时才resolve,导致Safari中直接进入reject分支,但调用代码未捕获该reject,触发了未处理Promise拒绝。
修复方案
1. 调整request函数的状态判断逻辑
修改xhr.onload中的判断条件,兼容本地文件请求的status=0情况:
function request (obj) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(obj.method || "GET", obj.url); if (obj.headers) { Object.keys(obj.headers).forEach(key => { xhr.setRequestHeader(key, obj.headers[key]); }); } xhr.onload = () => { // 兼容file协议下的成功请求(status为0且有响应内容) if ((xhr.status >= 200 && xhr.status < 300) || (xhr.status === 0 && xhr.response)) { resolve(xhr.response); } else { reject(xhr.statusText || "请求失败"); } }; xhr.onerror = () => reject(xhr.statusText || "网络错误"); xhr.send(obj.body); }); }
2. 为Promise添加错误捕获
不管用await还是链式调用,都必须捕获reject,避免未处理Promise拒绝:
- 用await+try/catch的写法:
try { const data = await request({url: "test.html"}); document.getElementById("targetDiv").innerHTML = data.toString(); } catch (err) { console.error("加载本地文件失败:", err); }
- 用then+catch的链式写法:
request({url: "test.html"}) .then(data => { document.getElementById("targetDiv").innerHTML = data.toString(); }) .catch(err => { console.error("加载本地文件失败:", err); });
补充说明
Safari对本地文件的权限管控比Chrome更严格,file://协议下的请求状态返回差异是常见兼容性问题。因为你仅用于本地测试,上述修改完全满足需求,无需考虑额外安全限制。
内容的提问来源于stack exchange,提问作者jorge_quintanilha
相关产品推荐
相关产品推荐

