为什么请求不存在的相对路径时$.ajax会重复加载根路径+index.html
问题解答
1. 现象产生的原因
你所使用的web服务器(Nginx/Apache等)默认配置了不存在路径重定向到index.html的规则,该规则一般用于支持单页应用(SPA)的前端路由,作用是所有未匹配到静态资源的请求都会返回首页内容,状态码为200而非404。
当请求的CUsermenu.txt不存在时,服务器不会返回404错误,而是返回完整的index.html内容。jQuery ajax收到200状态码会判定请求成功,直接走done回调,把index.html内容插入到#CUsermenu节点中。插入的内容里包含和当前页面完全相同的加载脚本,脚本会再次执行请求逻辑,就形成了循环加载的现象。
2. 操作存在的问题
- 没有对请求返回的内容做有效性校验:你默认请求txt文件要么成功返回文本、要么失败走fail回调,但实际上服务器返回了200状态码的HTML内容,ajax不会触发fail逻辑,你直接将返回内容插入到了页面中。
- 没有考虑服务器的fallback配置对请求结果的影响:你假定不存在的资源一定会返回404状态码,但实际场景中很多站点都会配置资源不存在时返回首页的规则。
3. 规避方案
- 修改服务器配置:针对静态资源请求(后缀为
.txt、.jpg、.css、.js等的文件),配置为资源不存在时直接返回404状态码,不重定向到index.html。 - 添加返回内容校验:在done回调中先校验响应的Content-Type是否符合预期(请求txt的话应该是
text/plain),如果响应为text/html或者内容中包含<html>、<head>等HTML标签,就判定为无效内容,手动执行失败逻辑,不插入到页面中。 - 配置ajax阻止重定向:如果你使用的是jQuery 3.x及以上版本,可以在ajax参数中添加
redirect: 'error',遇到重定向时会直接触发fail回调,不会返回重定向后的内容。 - 过滤插入内容:如果无法修改服务器配置,可以在插入响应内容前做过滤,只提取你需要的列表项内容,避免将完整的HTML页面插入到节点中。
修正后的代码参考
<script> $(function () { Promise.all([LoadCUsermenu('CUsermenu.txt')]).then( ()=>{console.log('Promise fulfilled')} ); console.log('Do the rest of the stuff') }); function LoadCUsermenu(filename) { return $.ajax({ url: filename, redirect: 'error' // 重定向直接触发错误回调 }).done(function (response, responseStatus, xhr) { // 校验内容类型是否为纯文本 const contentType = xhr.getResponseHeader('Content-Type'); if (!contentType.includes('text/plain') || response.includes('<html')) { // 无效内容手动走失败逻辑 handleLoadFail(); return; } console.log('Usermenu present...Loading'); $('#CUsermenu').html(response) }).fail(function (xhr, textStatus, errorThrown) { handleLoadFail(); }) } function handleLoadFail() { console.log('No Usermenu present...'); $('#CUsermenu').html("<li>Nothing there</li>") } </script> <head> </head> <body> <ul id='CUsermenu'></ul> <div><p>Will this be loaded repetetively???</p></div> </body>
内容的提问来源于stack exchange,提问作者Hans Rottier
相关产品推荐
相关产品推荐

