一个运行了多年的老项目里,网络请求几乎都是通过jQuery的$.ajax完成的,最近新写的模块开始采用Fetch API,代码看起来更简洁,但一旦在IE11上运行就报错,提示Promise未定义或fetch不存在。这类问题的根源在于IE11既不支持Fetch,对Promise的支持也不完整,必须通过polyfill补齐能力。本文围绕如何在保留jQuery Ajax的同时,为IE11配置一套稳定可靠的Fetch polyfill方案展开说明。

为什么Fetch在IE11中必须依赖polyfill
Fetch API建立在两个基础之上:一是Promise对象,二是基于XMLHttpRequest重新封装的请求机制。IE11虽然原生支持XMLHttpRequest,但它的Promise实现是残缺的,甚至可以说IE11根本没有标准的Promise,微软在Edge中才提供了完整实现。这意味着即使只引入whatwg-fetch这一个polyfill,代码依然会在创建Promise的地方报错。
更麻烦的是,IE11的Promise残缺实现有时会让问题变得隐蔽。某些页面在没有显式使用Promise时一切正常,一旦新代码里写了fetch(url).then(),控制台立刻抛出Promise未定义的错误。开发者容易误以为是自己代码写错了,实际上这是环境能力缺失,必须从外部注入实现。
因此正确的思路是分层补齐:先用promise-polyfill提供符合规范的Promise实现,再引入whatwg-fetch提供fetch函数本身。两者存在严格的依赖顺序,顺序颠倒会导致fetch内部引用到IE11那个残缺的原生Promise,出现then回调不执行的诡异现象。
polyfill的选型与引入顺序
Promise的polyfill方案里,promise-polyfill是经过大量项目验证的选择,体积小、实现完整,还额外提供了finally方法。ES6-Promise也是一个选项,但体积更大,对于只需要补齐基础能力的场景没有必要。fetch部分首选whatwg-fetch,它就是官方规范对应仓库产出的polyfill,兼容性最可靠。
引入顺序必须遵守先Promise后fetch的原则,示例如下:
<script src="js/promise-polyfill.min.js"></script> <script src="js/whatwg-fetch.min.js"></script> <script src="js/jquery.min.js"></script> <script src="js/app.js"></script>
把polyfill放在最前面,可以确保后续所有脚本,包括jQuery内部逻辑和新写的Fetch代码,都能拿到正确的Promise实现。如果项目使用了构建工具,也可以在入口文件中通过import引入:
// 入口文件最顶部,顺序不能颠倒
require('promise-polyfill/src/polyfill');
require('whatwg-fetch');需要注意whatwg-fetch是一个条件导出的包,它的package.json中main字段指向的代码会自动检测浏览器能力,只在缺少fetch的环境中注入实现,不会覆盖现代浏览器的原生fetch,这一点可以放心使用。
与jQuery Ajax共存时的几个关键配置
第一是全局污染问题。jQuery的$.ajax不依赖全局Promise(旧版本基于回调,3.x版本基于自身实现),所以polyfill不会干扰它,两者可以安全共存。但要避免在项目中混用两种异步风格处理同一个业务流程,建议新功能统一走fetch,老代码保持不动,逐步迁移而不是一次性重写。
第二是跨域凭证的默认行为差异。jQuery Ajax中xhrFields: { withCredentials: true }才携带Cookie,而fetch polyfill默认credentials行为遵循老规范,即same-origin。如果接口跨域且需要Cookie,必须显式声明:
fetch('https://api.ipipp.com/user/info', {
method: 'GET',
credentials: 'include', // 跨域携带Cookie
headers: {
'Content-Type': 'application/json'
}
})
.then(function(res) { return res.json(); })
.then(function(data) { console.log(data); });第三是错误处理习惯的差异。jQuery Ajax里网络错误走error回调,HTTP状态码404、500也会触发error;而fetch只要请求发出去了,无论状态码多少都会进入then,只有网络层失败才会reject。迁移代码时必须手动判断res.ok或res.status,否则业务错误会被当成正常数据往下走,这是老项目改造中最容易埋雷的地方。
上线前的验证与兜底策略
配置完成后,建议在IE11真实环境中完整跑一遍核心流程,重点关注三点:Promise相关的报错是否消失、跨域请求是否正常携带会话信息、页面里老jQuery请求是否依然工作正常。可以用IE11的开发者工具查看网络面板,确认polyfill注入的fetch实际发出的请求头与之前jQuery发出的保持一致。
另外可以加一层运行时检测作为兜底,在polyfill加载失败或被广告插件拦截时降级回jQuery Ajax:
function request(url, options) {
if (typeof window.fetch === 'function') {
return fetch(url, options);
}
// 降级方案:用jQuery的Deferred包装ajax
var d = $.Deferred();
$.ajax({
url: url,
type: (options && options.method) || 'GET',
success: function(data) { d.resolve(data); },
error: function(xhr) { d.reject(xhr); }
});
return d.promise();
}这套封装让上层业务代码感知不到底层是fetch还是jQuery,即使polyfill在某个极端环境下没有生效,页面功能也不会完全瘫痪。总的来说,promise-polyfill加whatwg-fetch的组合,配合正确的引入顺序和对凭证、错误处理差异的适配,就能让jQuery Ajax与Fetch API在IE11下和平共处,为后续彻底淘汰IE支持打好基础。
jQuery AjaxFetch APIpolyfill修改时间:2026-09-08 12:49:02