前言:昨天,同事修改项目升级插件时遇到了一个ajax 报错,如下:
$.ajax({
type : "get",
async:false,
timeout:3000,
url : "http://10.10.10.26:808/servlet/updateLog?line=1",
dataType : "jsonp",//数据类型为jsonp
jsonp: "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 function
var 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];
}
});