jquery延迟了异步调用

时间:2017-07-18 12:55:58

标签: ajax jquery-deferred

请找到以下代码段:

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;
  });
});

First Name文本字段附带了onblur事件,在通常情况下工作正常但是当焦点在“First Name”上并且单击“Submit”时,调用submit函数而不是等待onblur事件为完成。

2 个答案:

答案 0 :(得分: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();
    });

答案 1 :(得分:0)

好的,如果你想在焦点离开#firstname时调用populatePage(),并且如果用户也点击了提交按钮并且你希望提交操作等待该模糊操作完成,你可以做这样:

$('#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 arm中返回一个promise,这样你的函数始终会返回一个promise。如果在else子句中没有其他任何操作,那么在jQuery中返回已经解析的promise的快捷方式就是return $.when();
  4. 警告.done()是特定于jQuery的,而不是标准的承诺行为。如果您已经使用jQuery 3.x或更高版本,那么您应该切换到.then(),然后您的承诺将表现得像承诺标准。