[jQuery]$.ajaxで空のレスポンスの取り扱いにハマった。


スクリーンショット 2016-05-13 14.56.53

jQueryのAjax通信で、ステータスコード200を返していてもレスポンスの中身が空だと通信失敗とみなされる場合があるらしいです。

$(function(){

  $('#awesome-btn').click(function(){
    $.ajax({
      type: 'POST',
      url: 'http://localhost:8080/api/create',
      data: new AwesomeDto(),
      contentType: 'application/json',
      dataType: 'JSON'
    })
    .done(function(data){
      console.log('done!');
      //その後の処理
    })
    .fail(function(error){
      console.log(error);
    });
  })


});

送り先のAPIのコントローラ構成(java+Spring Boot)はこんな感じ


@RequestMapping("/")
@RestController
public class AwesomeController{
  
  @Inject
  private AwesomeService service;

  @RequestMapping("/create")
  @ResponseStatus(code=HttpStatus.OK)
  public void create(@RequestBody AwesomeDto dto){
    service.save(dto);
  }

}

これを実行すると、正常終了でもerror側のメソッドが実行されてしまいます。
理由は、$.ajaxのoptionのdataTypeでJSONを明示的に指定してしまっているので、空の文字列を無理やりJSONにパースしようとしてエラーになるっぽいです。

試しに、ブラウザのコンソールで

JSON.parse('');

と実行するとエラーになるはずです。

回避策は、dataTypeの指定を外すこと。
jQuery#Ajaxのドキュメントには以下のように記述してあります。

サーバから返されるデータの型を指定します。省略した場合は、jQueryがMIMEタイプなどを見ながら自動的に判別します。

省略すると、空レスポンスを返しても「あ、これ空だ」と内部で判断してよろしくdone側のメソッドが実行されます。

GW中にjQuery書いててここで2時間くらいハマった。。。