2017-07-18 70 views
0

請找到下面的代碼片段:的jQuery與異步延期調用

HTML:

<div> 
<span> First Name : <input type="text" id="firstName" name="First Name"/></span> 
</div> 
<br/> 
<div> 
<span>Student Id: <input type="text" id="studentId" name="studentId"/></span> 
<span>Teacher Id: <input type="text" id="teacherId" name="teacherId"/></span> 
</div> 
<br/> 
<div> 
<span>Student Name : <input type="text" id="stdLastName" name="stdLastName"/></span> 
<span>Student Age :<input type="text" id="stdAge" name="stdAge"/></span> 
</div> 
<br/> 
<div> 
<span>Teacher Name : <input type="text" id="tchrLastName" name="tchrLastName"/></span> 
<span>Teacher Age : <input type="text" id="tchrAge" name="tchrAge"/></span> 
</div> 
<br/> 
<input type="button" value="Submit" id="submit"/> 

的Javascript:

$('#firstName').focus(); 

var d1= new $.Deferred(); 

$('#firstName').blur(populatePage()); 

//called on blur of first name 
function populatePage() { 
    $.when(populateStdDetails(),populateTchrDetails()).done(function(resp1, resp2){ 
      $('#stdLastName').val(resp1[0].stdName); 
     $('#stdAge').val(resp1[0].age); 
     $('#tchrLastName').val(resp2[0].stdName); 
     $('#tchrAge').val(resp2[0].age); 
      console.log('All details populated....'); 
     d1.resolve(); 

    }); 
    return d1; 
} 

//first ajax call 
function populateStdDetails() { 
    if($('#firstName').val() != '' && $('#studentId').val() !='') { 
     return $.ajax({ 
     url : '/someURL?studentId='+studentId+'&firstName='+firstName, 
     type :'GET', 
     contentType:'json' 
    }); 
    } 
} 

//second ajax call 
function populateTchrDetails() { 
    if($('#firstName').val() != '' && $('#teacherId').val() !='') { 
     return $.ajax({ 
     url : '/someURL?teacherId='+teacherId+'&firstName='+firstName, 
     type :'GET', 
     contentType:'json' 
    }); 
    } 
} 

$('#submit').click(function(e){ 
    //wait for the ajax calls to be completed 
    $.when(populatePage()).done(function(e){ 
    console.log('All done !!!!'); 
    //Move to next page; 
    }); 
}); 

名字文本字段中有一個onblur事件連接工作正常在通常的情況下,當單擊焦點在「名字」和「提交」時,調用提交函數而不是等待onblur事件完成。

+0

請注意,在真實代碼中,jQuery中的ajax請求已經返回自己的承諾,因此您不需要將它們包裝在另一個承諾中。如果您向我們展示您的真實代碼,我們實際上可以分享如何最好地使用承諾與真正的代碼。使用make believe代碼的理論問題很少像真實的代碼那樣有價值的參考,在這些代碼中,貢獻者可以向您展示所有可以做得更好的事情。 – jfriend00

+0

@ jfriend00:請找到我描述實際需求的小提琴:https://jsfiddle.net/diptesh2007/ebz6ey1m/ – diptesh2007

+0

該代碼有很多錯誤。對於初學者來說,它充滿了[延期反模式](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns)。如果您根據發佈指南將此代碼添加到您的問題中,我們可以向您展示更多更好的方法來完成您正在做的事情。正如我懷疑的那樣,你根本不需要創建新的承諾,因爲你已經有了可以直接使用的'.ajax()'調用的承諾。 – jfriend00

回答

1

您已將deferred.resolve放置在您的超時函數的錯誤位置。做這樣的方式:

function doSomething(deffered) { 
    $('#log').append('doSomething'); 
    deferred.resolve(); 
    return deferred; 
}; 

function ajaxRequests1(deferred) { 
    setTimeout(function(){ 
     $('#log').append('......ajaxRequests1'); 
     deferred.resolve(); 
    }, 1000); 
    return deferred; 
}; 

function ajaxRequests2(deferred) { 
    setTimeout(function(){ 
     $('#log').append('.....ajaxRequests2'); 
     deferred.resolve(); 
    }, 5000); 
    return deferred; 
}; 

var func1 = function() { 
     var promise = new $.Deferred(); 
     ajaxRequests1(promise); 
     return promise; 
    } 

var func2 = function() { 
     var promise = new $.Deferred(); 
     ajaxRequests2(promise); 
     return promise; 
} 

var stepFinal = function() { 
     var promise = new $.Deferred(); 
     doSomething(promise); 
     return promise; 
} 

$.when(func1().promise(), func2().promise()) 
    .done(function() { 
      stepFinal().done(); 
    }); 
+0

非常感謝!!我完全忽略了這個東西...... – diptesh2007

0

OK,如果你想populatePage()當焦點離開#firstname,如果用戶同時點擊了提交按鈕被稱爲並且要提交操作等待模糊動作到結束,你可以這樣做:

$('#firstName').blur(function(e) { 
    // call populatePage and set the resulting promise as a data item so 
    // the submit handler can get access to it 
    var self = $(this); 
    var p = populatePage(); 
    self.data("blurPromise", p); 

    // when this promise is done, clear the blurPromise 
    p.always(function() { 
     self.removeData("blurPromise"); 
    }); 
}); 

//called on blur of first name 
function populatePage() { 
    return $.when(populateStdDetails(),populateTchrDetails()).done(function(resp1, resp2){ 
     $('#stdLastName').val(resp1[0].stdName); 
     $('#stdAge').val(resp1[0].age); 
     $('#tchrLastName').val(resp2[0].stdName); 
     $('#tchrAge').val(resp2[0].age); 
     console.log('All details populated....'); 
    }); 
} 

//first ajax call 
function populateStdDetails() { 
    if($('#firstName').val() != '' && $('#studentId').val() !='') { 
     return $.ajax({ 
      url : '/someURL?studentId='+studentId+'&firstName='+firstName, 
      type :'GET', 
      contentType:'json' 
     }); 
    } else { 
     // just return already resolved promise 
     return $.when(); 
    } 
} 

//second ajax call 
function populateTchrDetails() { 
    if($('#firstName').val() != '' && $('#teacherId').val() !='') { 
     return $.ajax({ 
      url : '/someURL?teacherId='+teacherId+'&firstName='+firstName, 
      type :'GET', 
      contentType:'json' 
     }); 
    } else { 
     return $.when(); 
    } 
} 

$('#submit').click(function(e){ 
    // get blur promise or dummy resolved promise 
    var p = $("#firstName").data("blurPromise") || $.when(); 
    p.then(function() { 
     // do your submit logic here 
     // The onBlur handler is done now 
    }); 
}); 

事情我已經在你的承諾處理代碼更新:

  1. 直接使用的$.ajax()承諾沒有在另一個包裝他們諾言。
  2. 直接使用$.when()承諾,但不包含在另一個承諾中。
  3. 當使用if語句決定是否執行異步操作時,通常最好也在else設備中返回承諾,以便您的函數始終返回承諾。如果else子句中沒有別的事情要做,那麼在jQuery中返回一個已經解決的承諾的快捷方式就是return $.when();
  4. 被警告.done()是jQuery特有的,而不是標準的承諾行爲。如果您已經使用jQuery 3.x或更高版本,那麼您應該切換到.then(),然後您的承諾將表現得像諾言標準。
+0

謝謝你的迴應。由於第一個文本字段附帶了一個onblur事件,請考慮點擊焦點在「First Name」和「Submit」字段時會發生什麼。 onblur事件被調用,並且「Submit」函數將被調用。我希望在提交函數執行之前完成onblur函數。你認爲e.preventDefault()可以防止模糊事件嗎? – diptesh2007

+0

@ diptesh2007 - 我試圖瞭解這裏的所有用例。如果焦點位於First Name並且用戶單擊提交按鈕,是否只需要調用一次'populatePage()',然後在完成後提交表單?如果用戶在其他領域,你是否也想在提交之前調用'populatePage()'一次,然後在完成後提交表單?那麼,你只是想在失去焦點或提交時調用populatePage()?另外,有沒有一個實際的'

'?您的HTML不顯示這些標籤。 – jfriend00

+0

我想populatePage()僅在當前正在發生的「First Name」字段的onblur期間被調用。在提交期間,我只想要調用提交函數而不管哪個字段具有焦點,但是如果「名字」具有焦點並單擊「提交」,則當前填充的頁面()將被調用。在我們的例子中,表單是通過ajax提交的,而不是通過默認的表單操作。 – diptesh2007