今天同事在用jQuery的ajax方法去調用一個jsonp的api時,服務端出現了500錯誤,但是前端的jQuery代碼卻沒有觸發error事件,代碼如下:
$.ajax({ url: 'http://ptres.37.com/js/sq/modules/base44.js', type: 'GET', dataType: 'jsonp' }) .done(function() { console.log("success"); }) .fail(function() { console.log("error"); }).always(function(){ console.log("always"); });
如上的一段代碼,在服務端出錯時(http狀態碼為:5XX、4XX),ajax綁定的done, fail, always方法竟然一個都沒有被觸發。挺意外的,為什么這樣呢?難道是jQuery的bug?
仔細思考下jsonp的實現原理,其實不難找出問題的原因。
jsonp調用時其實是在header中創建一個script的dom節點,然后通過script的資源調用方式去向遠程服務器發送請求的,問題的關鍵就在這個script標簽上。如果想知道這個資源地址有沒有請求成功,我首先想到的是onload和onerror這兩個回調函數,遺憾的是,ie6,7,8都是不支持script的onload和onerror回調!我想,這個應該是jquery無法捕獲到這個錯誤的原因吧。
那么有沒有其它辦法來處理這個錯誤呢,答案是有的,並且很簡單,只要加上timeout參數即可:
$.ajax({ url: 'http://ptres.37.com/js/sq/modules/base44.js', type: 'GET', timeout: 2000, dataType: 'jsonp' }) .done(function() { console.log("success"); }) .fail(function() { console.log("error"); }).always(function(){ console.log("always"); });