以前ちょろっとJavaScript(jQuery)を書いた際にajaxを使用したのですが、
題名の通り、正常にレスポンスが取得できているのにも関わらず、
失敗(fail)として処理されてしまう現象に出くわしました。
その時は軽く調べて暫定的に対応してしまったので、しっかり調べてみました。
備忘の為に記事に残し、同じ現象に悩んでいる人の助けになれば。
現象を確認
$.ajax()を利用する場合、下記のような記述になるかと思います。
今回は例としてRedmineのチケット更新APIを実行します。
$.ajax({ type: 'PUT', url: '/issues/999.json', headers: { 'API-Key': API_KEY }, dataType: 'json', data: params contentType: 'application/json', }).done(function(resp) { console.log(resp); }).fail(function(jqXHR, textStatus, errorThrown){ console.log(jqXHR); console.log(textStatus); console.log(errorThrown); });
で、PUT処理がステータスコード=200(成功)で終了すれば、done()に処理が流れるはず。
が、fail()に入ってきてしまうと。
原因
原因は、下記の通り。
jQuery側でレスポンスの内容をJSON形式にパースしようとして、エラーとなっている。
下のキャプチャを見るとわかるかと思います。(”parsererror”としてfail()に入ってきている。)
以下、こちらのjQuery解説サイトから引用させて頂くと、dataType:”json”を指定した場合、
JSONとしてレスポンスを評価し、JavaScriptオブジェクトが返されます。 このJSONデータは厳格な作法によってパースされるため、奇形と判断されたJSONは拒絶され、パースエラーがスローされます。jQuery1.9からは、空のレスポンスも拒絶されるようになったため、 サーバーは代わりに
null
または{}
を返す必要があります。
との事。
私のRedmineではjQuery1.11.1が適用されておりますので、
空のレスポンスが拒絶されてパースエラーとなっていた、という事のようです。
対応
dataTypeを指定しない ⇒ エラーになる
いくつか同事象について説明しているサイトをみると、
との記載を見つけました。
これは、再び前述のjQuery解説サイトから引用させて頂きますが、
あなたが期待するサーバーから返されるデータの型を指定します。 もし指定されなければ、jQueryはレスポンスのMIME typeを元に推察することを試みます。
によるものと思われます。
が、今回のケースでは解決できませんでした。
これは下記キャプチャの通り、Redmine側のレスポンスヘッダのContent-Typeが
JSON指定されているから。
自動判定によりJSONと判断され、パースしようとしてパースエラーになってしまう
という事のようです。
dataTypeにtextを指定 ⇒ 解決
上記から、パースされなければエラーにならないと考えられる為、
プレーンテキストとして処理されるよう、textを指定すれば解決しました。
成功ロジックのdone()に入ってきました。
Redmineのチケット更新APIの成功レスポンスは、nullでも{}でもなく、””(空文字列)という事がわかります。
おわりに
なにかモヤモヤしていたので、原因がハッキリして良かった。
プログラマがレベルアップする方法って、こういう躓きを解決する積み重ねなんだろうなと。。。