的jQuery与异步延期调用

的jQuery与异步延期调用

问题描述:

请找到下面的代码片段:的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

您已将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

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