前言:昨天,同事修改项目升级插件时遇到了一个ajax 报错,如下:
$.ajax({type : "get",async:false,timeout:3000,url : "http://10.10.10.26:808/servlet/updateLog?line=1",dataType : "jsonp",//数据类型为jsonpjsonp: "jsonpCallback",//服务端用于接收callback调用的function名的参数success : function(data){console.log(data)},error:function(e){alert('fail');console.log(e);},complete:function(r,t){console.log(r);console.log(t)}})
net::ERR_CONNECTION_TIMED_OUT --连接超时
排查原因是:发ajax请求时,该日志服务正在启动(服务可能没有起来),有时间差。
但是,有了新的疑问-->为什么没走error和complete 回调呢?
查资料得知:这是由于这次请求是跨域的jsonp;
JQuery跨域请求的缺陷:错误处理
跨域请求可能会失败,比如对方服务器的安全设置拒绝接受来自我方的请求(我方不在对方的信任列表中),或者网络不通,或对方服务器已关闭,或者请求地址或参数不正确导致服务器报错等等。
在JQuery中,当使用ajax或getJSON发送请求后会返回一个jqXHR对象[3]。该对象实现了Promise协议,所以我们可以使用它的done、fail、always等接口来处理回调。例如我们可以用在它的fail回调中进行请求失败时的错误处理:
let xhr = $.getJSON(...);
xhr.fail(function(jqXHR, textStatus, ex) {alert('request failed, cause: ' + ex.message);
});
这种方式能够处理“正常的错误”,例如超时、请求被中止、JSON解析出错等等。但它对那些“非正常的错误”,例如网络不通、服务器已关闭等情况的支持并不好。此时不会走任何一个回调(success、error、complete...).
例如当对方服务器无法正常访问时,在Chrome下你会在控制台看到一条错误信息:
查看代码知道jsonpo跨域方式 会在head标签前部插入一个script标签;所以可用一下方法解决这个问题。
var head = document.head || $('head')[0] || document.documentElement; // code from jquery
var script = $(head).find('script')[0];
script.onerror(function(evt) {alert('error');//清除掉这个无效的script 节点if (script.parentNode) {script.parentNode.removeChild(script);}// delete jsonCallback global functionvar src = script.src || '';var idx = src.indexOf('jsonCallback=');if (idx != -1) {var idx2 = src.indexOf('&');if (idx2 == -1) {idx2 = src.length;}var jsonCallback = src.substring(idx + 13, idx2);delete window[jsonCallback];}
});