2013-02-26 49 views
1

我正在驗證包含用戶配置文件信息的表單,並且希望與我的服務器一起檢查用戶指定的用戶名是否已被使用。我已經定義了一個驗證方法,如下所示:爲什麼我的驗證ajax調用延遲整個驗證方法?

$.validator.addMethod(
    'check_username', 
    function(value, element, param) { 
     console.log('starting'); 
     var name_is_in_use = 0; 

     // Start the throbber. 
     $('form#user-profile-form input#edit-name').addClass('searching'); 

     // Hit the server and see if this name is already in use by someone else. 
     $.ajax({ 
      url: '/checkusername/' + value + '/" . $form['#user']->uid . "', 
      dataType: 'json', 
      data: {}, 
      async: false, 
      success: 
       function(data) { 
         console.log('back from the server'); 
         name_is_in_use = data; // unnecessary, but whatever 

         // Kill the throbber 
         $('form#user-profile-form input#edit-name').removeClass('searching'); 
        }, 
     }); 

     return name_is_in_use; 
    }, 
    'Sorry, but this username is already in use.'); 

總的來說,驗證過程起作用;我遇到的麻煩是在輸入字段上連接一個「忙碌」的悸動者以正常工作 - 悸動者永遠不會從其正常狀態變爲忙碌狀態。但是,在服務器上添加一些sleep()調用以誇大實際發生的情況後,我所看到的是這兩個console.log語句同時出現在控制檯中 - 在調用服務器之後已經完成。這就解釋了爲什麼我沒有看到跳動的變化 - .searching類在添加後立即被刪除。但我不明白的是,爲什麼我沒有看到我在想什麼應該要發生的事情:

  1. 我點擊瀏覽器領域火驗證方法。
  2. console.log('starting')顯示在控制檯中
  3. 跳動者打開。
  4. 有一個暫停,而服務器被調用,睡了一下, 返回其值,
  5. console.log('back')顯示了在該活動指示器被關閉控制檯

相反,我得到這個(忽略活動指示器類的變化):

  1. 我點擊瀏覽器領域火驗證方法。
  2. 有一個暫停,而服務器被調用,睡了一下, 返回其值,
  3. console.log('starting')顯示了在控制檯,然後,無延遲,
  4. console.log('back')在控制檯中顯示出來

步驟3和4幾乎同時發生。

我對此非常疑惑 - 看起來整個執行程序被ajax調用阻止了,這對我來說根本毫無意義。任何人都可以提供一些見解嗎?謝謝!

+0

'async:false'應該是'async:true' - 更多地閱讀這個設置。異步設置爲false會使請求異步。 http://api.jquery.com/jQuery.ajax/ – Pebbl 2013-02-26 23:31:30

+0

請參閱:http://stackoverflow.com/a/13579061/594235 – Sparky 2013-02-27 00:13:03

回答

3

這很簡單,那是因爲你在你的$.ajax通話設置asyncfalse

您正在製作同步請求,並且通常在完成此類事情時,Web瀏覽器在等待來自服務器的響應時往往看起來像懸掛。

+0

謝謝 - 接近但不完全。我將async更改爲true,並將「return name_is_in_use」移至成功處理程序中。好消息是,throbber現在正常工作,但是,由於ajax調用不再是異步的,驗證方法立即返回一個「假」值。通過console.log,我可以看到ajax調用做正確的事情,但它不再爲驗證系統提供價值。有沒有辦法解決這個問題? – 2013-02-26 23:48:12

+0

是的,有。你需要做一個異步驗證。我從來沒有說你的驗證是在做了適當的AJAX請求之後纔會起作用:) – Alexander 2013-02-26 23:49:52

+0

@JimMiller,'data'格式是什麼? Validate插件的自定義方法正在尋找'return true'或'return false'。 'return 1'或'return 0'也起作用。 – Sparky 2013-02-26 23:50:43

0

好吧,我有一些不僅有效,但似乎相對原則。有人認爲它可能對別人有用......

$('form#user-profile-form').validate({ 
    debug: true, 
    rules: { 
     name: { 
      required: true, 
      regexp: /\W/, 
      remote: { 
       url: '/checkusername', 
       type: 'post', 
       data: { 
        username: function() { return $('#edit-name').val() }, 
        uid: " . $form['#user']->uid . " 
        }, 
       beforeSend: function (jqXHR, settings) { 
           $('form#user-profile-form input#edit-name').addClass('searching'); 
          }, 
       complete: function (jqXHR, settings) { 
           $('form#user-profile-form input#edit-name').removeClass('searching'); 
          }, 
      } 
     } 
    }, 

    messages: { 
     name: { 
      regexp: '" . USERNAME_VALIDATION_MESSAGE . "', 
      remote: 'Sorry, but this username has been claimed by someone else.', 
      }, 
     ... 
     }, 
    errorPlacement: function(error, element) { 
     switch (element.attr('name')) { 
      case 'name': 
       error.insertAfter('.control-group.form-item-name > label'); 
       $('form#user-profile-form input#edit-name').removeClass('searching'); 
       break; 
      ... 

注意到這裏的有些事情:

  • 繁重通過remote選項,其中,作爲 醫生說做,是爲這樣的東西。 另一端的代碼如果用戶名可用則url返回JSONed 1/true,如果不是,則返回 。
  • beforeSend處理程序在服務器調用發生之前在驗證的開頭 處打開跳動者。
  • 在用戶指定非衝突名稱的情況下,complete處理程序會關閉跳動程序。
  • errorPlacement中的removeClass調用關閉 在服務器調用已返回並且報告了 錯誤的情況下跳動。
  • 因爲我有username兩個規則 - 對已在使用的試驗和 正則表達式測試,以確保指定的名稱是一個「字」 - 我要 指定每個相應的消息,在messages部分。

Phew。歡迎評論;感謝所有的幫助!