jQueryでsubmitイベントを一旦止めて、非同期してまた動かすの難しい

$('form').submit(function(){
  $.getJSON('url')
  .done(function(result){
    if (result) {
      //この場合はsubmitしたい(A)
    }
    //この場合はsubmitしない(B)
  })
  .fail(function(jqJHR){
    //失敗したらsubmitしない(B)
  });
  //一旦submitイベントは止める(C)
  e.preventDefault();
});

こんな感じで、submitイベントを拾って、その中で非同期通信して、その結果(A)の場合はsubmitをしたい。$.getJSON()は非同期なのでdone()やfail()*1に処理が移る時にはsubmitの処理は進んでしまいます。なので、(C)でe.preventDefault()*2でsubmitイベントを止めておく必要があります。で、$.getJSON()の結果によっては、submitを継続させたいんですが、イベントを一旦止めてやっぱり動かす方法が分からずはまりました。

一応の解決策

var onSubmit = function(){
  $.getJSON('url')
  .done(function(result){
    if (result) {
      //この場合はsubmitしたい(A)
      $('form').unbind('submit', onSubmit);
      $('form').submit();
    }
    //この場合はsubmitしない(B)
  })
  .fail(function(jqJHR){
    //失敗したらsubmitしない(B)
  });
  //一旦submitイベントは止める(C)
  e.preventDefault();
});
$('form').bind('submit', onSubmit);

bindする形にしておいて、(A)のとこでsubmitをトリガーで動かします。これだとsubmitイベントの続きではなく、もう一度submitイベントが発火されるので、ループしてしまう事に。なので、直前にunbindすると言う、ちょっと無理やりな方法です。e.preventDefault()で止めたイベントを、動かすメソッドとか無いんだろうか。

ちなみに(B)のとこは、そもそもsubmitイベントが(C)で止められてるので、何もしなくても大丈夫です。

jQueryのevent.preventDefault()

IEはe.preventDefault()が無く、代わりにe.returnValue = falseをするという独自仕様です。普段はe.preventDefault()じゃなくってreturn falseばかり使ってるので、気になりました。
今回e.preventDefault()を使ったのはeオブジェクトに止めたイベントを再開させるメソッドがあるかもと思った名残だったり。

	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}

		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();

		// otherwise set the returnValue property of the original event to false (IE)
		} else {
			e.returnValue = false;
		}
	},
https://github.com/jquery/jquery/blob/1.6/src/event.js#L611

jQuery内ではjQueryのEventオブジェクトで、ちゃんとIE用のe.returnValue = falseが入ってました。

環境

jQuery 1.5.1 1.6.1

*1:や普通のコールバック

*2:もしくはreturn false