14

HTML5 setCustomValidity() メソッド [古いブラウザ用の webshims ライブラリを使用] を使用して、次のページに進む前に電子メールの AJAX 検証を行うページがあります。

これを機能させるには、$.ajax() 呼び出しで async オプションを false に設定して同期させ、AJAX 応答を保留中のページをブロックします。そうしないと、ajax 呼び出しが戻る前にフォームが送信され、検証が無効になります。

<script>
  function validateEmailRegistered(input) {
    if (input.setCustomValidity === undefined) return;
    var err = 'Email address not found';
    $.ajax({
      url: 'email-is-registered.php', 
      data: { email: input.value }, 
      async: false, 
      success: function(data) {
        var ok = data=='true';
        input.setCustomValidity(ok ? '' : err)
      }
    });
  }
</script>

<form method="get" action="nextpage.php">
  <input name="email" id="email" type="email" required
    onChange="validateEmailRegistered(this)">
  <button type="submit">go</button>
<form>

async オプションは jQuery 1.8 で廃止される予定です。

非同期オプションなしでこのブロッキング アクションを実現するにはどうすればよいですか?

4

6 に答える 6

10

http://bugs.jquery.com/ticket/11013#comment:40

同期 ajax リクエストでの Deferred/Promise 機能の使用は、1.8 で非推奨になりました。.thenasync: false を指定した $.ajax メソッドはサポートされていますが、またはなどの Promise メソッドではなく、コールバック パラメーターを使用する必要があります.done

したがって、success/complete/error ハンドラを使用している場合でも、async:false. 詳細については、上記の jquery チケットを参照してください。

于 2012-10-26T18:13:20.547 に答える
2

jQuery 1.8 以降、jqXHR ($.Deferred) で async: false を使用することは推奨されなくなりました。完全/成功/エラーのコールバックを使用する必要があります。

http://api.jquery.com/jQuery.ajax/ (非同期セクション)

これは少し面倒だと思いました...開発者は、プラットフォームが許可するものである場合、ブロック呼び出しを行う選択肢を与えられるべきですasync: false-なぜそれを制限するのですか? ハングの影響を最小限に抑えるために、タイムアウトを設定するだけです。

それにもかかわらず、私は現在 1.8 でキューを使用しています。これはノンブロッキングであり、非常にうまく機能します。Sebastien Roch は、関数をキューに入れ、それらを実行/一時停止できる使いやすいユーティリティを作成しました。 https://github.com/mjward/Jquery-Async-queue

    queue = new $.AsyncQueue();
    queue.add(function (queue) { ajaxCall1(queue); });
    queue.add(function (queue) { ajaxCall2(queue); });
    queue.add(function() { ajaxCall3() });
    queue.run();

最初の 2 つの関数では、オブジェクトを呼び出しに渡しqueueます。呼び出しは次のようになります。

function ajaxCall1(queue) {
    queue.pause();
    $.ajax({
       // your parameters ....
       complete: function() {
         // your completing steps
         queue.run();
       }
    });
}

// similar for ajaxCall2

queue.pause();各関数の先頭にある に注意し、ステートメントqueue.run()の最後でキューの実行を続行します。complete

于 2012-10-25T14:43:21.710 に答える
0

メールの有効性を確認するまでフォームを送信させないように設定している場合は、disabled属性を使用して送信ボタンを開始し、コールバックを設定します$('form button').removeAttr('disabled');

そうは言っても、私は他の人たちと一緒です-ただ彼らにフォームを提出させてください!通常、人々はそれを正しく理解し、あなたはエラーなしでそれらを正しく通過させます...

于 2012-06-18T15:30:51.073 に答える
0

いずれにせよ、送信時に完全なフォーム検証を行うと想定しているため、入力時の電子メール検証が中断され、フォーム送信が優先されても問題はないでしょう。

ユーザーがフォームを送信するときに、「validateEmailRegistered」AJAX リクエストを中止することだと思います。次に、電子メールの検証を含む、通常どおり完全なサーバー側のフォーム検証を実行します。

入力時の検証についての私の理解では、フォームが送信されたときにフォームを検証する代わりになるものではなく、細心の注意を払っているということです。したがって、フォームの送信をブロックするのは意味がありません。

于 2012-06-16T11:24:57.370 に答える
0

働き方を少し変える必要があると思います。ブロッキングを達成しようとするのではなく、ノンブロッキングを受け入れてください。

私はこれをしたいと思います: - 電子メールでの検証を維持します。非同期にします。有効な場合は、変数のどこかにフラグを設定して、問題がないことを確認します。- form.submit() にコールバックを追加して、電子メールが (変数を使用して) OK かどうかを確認し、そうでない場合は送信を防止します。

このようにして、Web ブラウザー UI をフリーズすることなく、非同期呼び出しを維持できます。

- [編集] -

これは、あなたが既に持っているものに基づいて例のために書いた簡単なコードです。

参考までに、「プロミス」と呼ばれるプログラミングの概念 (先物と据え置きは別の用語です) は、あなたが抱えている問題を正確に解決するために発明されました。

これが何であるか、および JavaScript でそれらを使用する方法 (dojo または jQuery を使用) に関する記事は次のとおりです。 -with-promises.aspx

<script>
  function validateEmailRegistered(input) {
    if (input.setCustomValidity === undefined) return;
    var err = 'Email address not found';
    $.ajax({
      url: 'email-is-registered.php', 
      data: { email: input.value }, 
      success: function(data) {
        var ok = data=='true';
        input.setCustomValidity(ok ? '' : err);
        // If the form was already submited, re-launch the check
        if (form_submitted) {
            input.form.submit();
        }
      }
    });
  }

  var form_submitted = false;

  function submitForm(form) {
    // Save the user clicked on "submit"
    form_submitted = true;
    return checkForm(form);
  }

  function checkForm(form, doSubmit) {
    if (doSubmit) {
        form_submitted = true;
    }
    // If the email is not valid (it can be delayed due to asynchronous call)
    if (!form.email.is_valid) {
        return false;
    }
    return true;
  }
</script>

<form method="get" action="nextpage.php" onsumbit="return submitForm(this);">
  <input name="email" id="email" type="email" required
    onChange="validateEmailRegistered(this)">
  <button type="submit">go</button>
<form>
于 2012-06-16T11:29:42.093 に答える
0

非同期で実行できます。

グローバル変数を作成します。私はこれを ajax_done_and_successful_flag と呼びます。プログラムの開始時に false に初期化します。Ajax 成功関数や Ajax エラー関数など、Ajax 関数のさまざまな場所でこれを true または false に設定します。

次に、検証関数の下部に送信ハンドラーを追加する必要があります。

submitHandler: function(form) {
   if (ajax_done_and_successful_flag === true) {
     form.submit()
   }
}  

問題は、コードが直線的に実行されていないことです。
Firebug の console.log ステートメントをコードに追加します。
実行順序を観察します。
Ajax 応答が最後に、または気が向いたときに返されることがわかります。 そのため、フォームが送信される前に検証関数が正しい Ajax 結果を待機するように
するには、submitHandler とグローバル フラグが必要です。

Ajax 応答からの画面への出力は、success 関数や error 関数などの Ajax 関数で行う必要があります。
検証関数の成功/エラー関数と同じ場所に書き込む必要があります。
このようにして、Ajax エラー メッセージは検証関数のエラー関数と調和します。
この概念は少しトリッキーに思えるかもしれません。
覚えておくべきことは、validate 関数の success 関数と error 関数は、Ajax 呼び出しの success 関数と error 関数と同じ場所に書き込んでいるということです。
エラー メッセージの場所は、ユーザーが入力を入力した場所のすぐ隣にあります。これにより、あなたが求めている素晴らしいユーザー エクスペリエンスが生まれます。

これが私のコードサンプルです。単純化しました。

jQuery-1.7.1
と jQuery 検証プラグイン 1.6
を実行しています。Firefox 14.0.1 を使用しており、Chrome 21.0 でも正常に試しました。

 var ajax_done_and_successful_flag = false;

 // Add methods
  ...

 $.validator.addMethod("USERNAME_NOT_DUPLICATE", function (value, element) {
   return this.optional(element) || validate_username_not_duplicate( );
  },
  "Duplicate user name.");

// validate
$(document).ready(function ( ) {
   $('#register_entry_form form').validate({
      rules: {
         username: {
         required: true,
         minlength: 2,
         maxlength: 20,
         USERNAME_PATTERN: true,
         USERNAME_NOT_DUPLICATE: true
        },    
    ...
    errorPlacement: function (error, element) { 
       element.closest("div").find(".reg_entry_error").html(error);
    },
    success: function(label) {
       label.text('Success!');
    } ,

    submitHandler: function(form) {   
       if (ajax_done_and_successful_flag === true ) {    
          form.submit();
       }
    }
  });
});

/* validation functions*/

function validate_username_not_duplicate() {

   var username_value = $('#username').val(); // whatever is typed in

   $.ajax({
      url: "check_duplicate_username.php",
      type: "POST",
      data: { username: username_value },
      dataType: "text",
      cache: false,
      //async: false,
      timeout: 5000,
      error: function (jqXHR, errorType, errorMessage) {
         ajax_done_and_successful_flag = false;

        if ( errorType === "timeout" ) {
           $('#username').closest("div").find(".reg_entry_error").html("Server timeout, try again later" );
        } else if ...

      },

      success:  function (retString, textStatus,jqXRH) {

        if ( retString === "yes") { // duplicate name 
           // output message next to input field        
           $('#username').closest("div").find(".reg_entry_error").html("Name already taken.");
           ajax_done_and_successful_flag = false;
        } else if ( retString === "no") { // name is okay
           // output message next to input field
           $('#username').closest("div").find(".reg_entry_error").html("success!");
           ajax_done_and_successful_flag = true;

        } else {
           console.log("in validate_username_duplicate func, success function, string returned was not yes or no." );
           $('#username').closest("div").find(".reg_entry_error").html("There are server problems. Try again later.");
           ajax_done_and_successful_flag = false;
       }
     } // end success function

   }); // end ajax call


  return true; // automatically return true, the true/false is handled in
              // the server side program and then the  submit handler

}

reg_entry_error は、テキスト入力のすぐ横の場所です。以下は、フォームの単純化されたコード サンプルです。

  <label class="reg_entry_label" for="username">Username</label>
  <input class="reg_entry_input" type="text" name="username" id="username" value="" />
  <span class="reg_entry_error" id="usernameError" ></span>  

これがあなたの質問に答えることを願っています。

于 2012-08-31T17:47:52.160 に答える