ひ孫

犬のこととか書いていきたい

ajax通信でdataType : scriptだのgetScriptだのしたときの失敗時ハンドリングできなかった話リトライ

はてなブログにインポートの際に ajax通信でdataType : scriptだのgetScriptだのしたときの失敗時ハンドリングできなかった話id:htzさんからコメントが再度付けられている事に気づいた。*1

ちょっとこのまま放っておくのも勿体ないので再度調査をしてみた。

今回jQuery 1.9で試している。

まず普通にjQueryを使った場合

// 存在するファイル
$.getScript("./javascripts/exist.js")
.done(function(){
console.log("[LOG] $.getScript load exist.js");
})
.fail(function(){
console.log("[LOG] $.getScript cannot load exist.js");
});
// 存在しないファイル
$.getScript("./javascripts/not_exist.js")
.done(function(){
  console.log("[LOG] $.getScript load not-exist.js");
}).fail(function(){
  console.log("[LOG] $.getScript cannot load not-exist.js");
})

で、consoleには

XHR finished loading: "http://localhost:3000/javascripts/exist.js?=1362066668626".
[LOG] $.getScript load exist.js
GET http://localhost:3000/javascripts/not_exist.js?
=1362066668627 404 (Not Found)
XHR finished loading: "http://localhost:3000/javascripts/not_exist.js?_=1362066668627".
[LOG] $.getScript cannot load not-exist.js *2 成功時、失敗時どちらもハンドリングできている。

そんで次。別ドメインなスクリプトを指定してみる。

$.getScript("http://s.hatena.ne.jp/js/HatenaStar.js")
.done(function(){
  console.log("[LOG] $.getScript load another domain script");
}).fail(function(){
  console.log("[LOG] $.getScript cannot load another domain script");
})
$.getScript("http://s.hatena.ne.jp/js/hogehogehoge_not_exist.js")
.done(function(){
  console.log("[LOG] $.getScript load another domain script");
}).fail(function(){
  console.log("[LOG] $.getScript cannot load another domain script");
})
})(jQuery)

result

GET http://s.hatena.ne.jp/js/hogehogehoge_not_exist.js?_=1362067011854 404 (Not Found) [LOG] $.getScript load another domain script

挙動が違う! なるほど。見比べてみるとローカルの方はXHR通信をしている。同じ関数でも全く別な挙動をしているということか。

OK。ここまでは理解した。でも結局<script>タグを埋め込むだけだとして、そのDOMにエラーハンドリングしてくれるなりしてくれたっていいじゃないか

ソースをみてみよう。

じゃあ実際にソースがどうなっているのか。

jquery-1.9_stable

script.onload = script.onreadystatechange = function( _, isAbort ) {

          if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {

見た感じやっぱり成功時しかハンドリングしてないみたい。

なるほど。

じゃあmasterでは・・・

  }).on(
    "load error",

おっ!エラーもキャッチしている!

ということで2.0では治っているみたいですね。

2.0の回避法を参考に解決策を出してみる。

var script = $("<script>").prop({
  src : "http://s.hatena.ne.jp/js/hogehogehoge_not_exist.js"
})
script.error(function(ev) {
  console.log("error");
});

document.head.appendChild(script[0]);

もはやgetScriptやってないし結構敗北感強い・・・・

ちなみにdocument.head.appendChild(script[0])$("head").append(script);では動かなかった。

これに関してはそのうち調べたい。

2013-03-02 追記: これって$.ajaxでも同じなのか気になったのでやってみた

var func = function(type){
  console.log("type:" + type);
  $.ajax({
    url :"http://gogogogogoggoogle.com", //適当に存在しないアドレス
    dataType : type,
    success : function(){
      console.log("[LOG] type:"+type+"$.ajax load ");
    },
    error : function(){
      console.log("[LOG] type:"+type+" cannot load");
    }
  });
}
var dataTypes = ["xml","html","script","json","jsonp","text"]
for(var i = 0; i < dataTypes.length  ; i++){
  func(dataTypes[i])
}

結果は以下のとおり

jQuery 1.9

type:xml
type:html
type:script
type:json
type:jsonp
type:text
[LOG] type:html cannot load
[LOG] type:xml cannot load
[LOG] type:text cannot load
[LOG] type:json cannot load

jQuery 2.0

type:xml
type:html
type:script
type:json
type:jsonp
type:text
[LOG] type:html cannot load
[LOG] type:xml cannot load
[LOG] type:json cannot load
[LOG] type:text cannot load
[LOG] type:script cannot load
[LOG] type:jsonp cannot load

*1:196日前って・・・

*2:見づらい・・・