我有以下JavaScript代码:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
我如何确保function2
仅在function1
完成后调用?
我有以下JavaScript代码:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
我如何确保function2
仅在function1
完成后调用?
Answers:
指定一个匿名回调,并使function1接受它:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable, function() {
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
function function1(param, callback) {
...do stuff
callback();
}
...do stuff
包含异步的内容怎么办?如预期的那样,Function2仍不会触发。我上面的注释中的示例显示,由于该foo()
函数中包含异步代码,因此即使bar()
在foo()
内容执行完毕后也不会触发它的内容,即使使用$.when().then()
一个接一个地调用它们也是如此。仅当(并且仅)...do stuff
代码中的所有内容严格同步时,此答案才有效。
callBack()
在完成所有n个异步调用之后触发。由于OP并未提及他在该函数中所做的工作,因此将其视为一级异步调用。
如果您使用的是jQuery 1.5,则可以使用新的Deferreds模式:
$('a.button').click(function(){
if(condition == 'true'){
$.when(function1()).then(function2());
}
else {
doThis(someVariable);
}
});
编辑:更新了博客链接:
丽贝卡·墨菲(Rebecca Murphy)在这里对此进行了出色的撰写:http : //rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/
$.when(function1).then(function2);
(没有调用函数的括号)?
function1
应该兑现承诺。在这种情况下,它必须是实际执行的功能,而不是引用。当resolve
在那个诺言上被调用时,然后function2
执行。通过假定function1
具有ajax调用,可以很容易地解释这一点。然后,done
回调将解决承诺。我希望这很清楚。
promises
,是ECMAScript 6
标准的JavaScript功能。如果目标平台不支持promises
,请用PromiseJs填充它。承诺是一种处理JavaScript中异步操作的新方法(更好的方法):
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable).then(function() {
//this function is executed after function1
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
function function1(param, callback) {
return new Promise(function (fulfill, reject){
//do stuff
fulfill(result); //if the action succeeded
reject(error); //if the action did not succeed
});
}
对于这个简单的示例,这似乎是一笔巨大的开销,但是对于更复杂的代码,这比使用回调要好得多。您可以使用多个then
语句轻松地链接多个异步调用:
function1(someVariable).then(function() {
function2(someOtherVariable);
}).then(function() {
function3();
});
您还可以轻松包装jQuery延迟(从$.ajax
调用返回):
Promise.resolve($.ajax(...params...)).then(function(result) {
//whatever you want to do after the request
});
如@charlietfl所指出的,由jqXHR
返回的对象$.ajax()
实现Promise
接口。因此,实际上没有必要将其包装在中Promise
,可以直接使用:
$.ajax(...params...).then(function(result) {
//whatever you want to do after the request
});
Promise.resolve
包装$.ajax
是因为反模式$.ajax
的回报thennable承诺
Promise
,它只是实现了接口。我不确定将实数传递Promise
给它的then
方法时它的行为,或者Promise.all
将a jqXHR
和a Promise
传递给它时a 会做什么。为此,我需要做进一步的测试。但是,谢谢您的提示,我将其添加到答案中!
$.ajax.then
是什么都不新鲜
或者,您可以在一个函数完成时触发自定义事件,然后将其绑定到文档:
function a() {
// first function code here
$(document).trigger('function_a_complete');
}
function b() {
// second function code here
}
$(document).bind('function_a_complete', b);
使用此方法,函数“ b”只能在函数“ a”之后执行,因为仅当函数a完成执行时才存在触发器。
你可以这样
$.when(funtion1()).then(function(){
funtion2();
})
如果必须在方法2、3、4之后执行方法1,则以下代码段可以是使用JavaScript中的Deferred对象的解决方案。
function method1(){
var dfd = new $.Deferred();
setTimeout(function(){
console.log("Inside Method - 1");
method2(dfd);
}, 5000);
return dfd.promise();
}
function method2(dfd){
setTimeout(function(){
console.log("Inside Method - 2");
method3(dfd);
}, 3000);
}
function method3(dfd){
setTimeout(function(){
console.log("Inside Method - 3");
dfd.resolve();
}, 3000);
}
function method4(){
console.log("Inside Method - 4");
}
var call = method1();
$.when(call).then(function(cb){
method4();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
如果function1是某个同步功能,您希望将其转换为一个异步功能,因为它需要一些时间才能完成,并且您无法控制它来添加回调:
function function1 (someVariable) {
var date = Date.now ();
while (Date.now () - date < 2000); // function1 takes some time to complete
console.log (someVariable);
}
function function2 (someVariable) {
console.log (someVariable);
}
function onClick () {
window.setTimeout (() => { function1 ("This is function1"); }, 0);
window.setTimeout (() => { function2 ("This is function2"); }, 0);
console.log ("Click handled"); // To show that the function will return before both functions are executed
}
onClick ();
输出将是:
Click handled
...并在2秒后:
This is function 1
This is function 2
之所以可行,是因为调用window.setTimeout()会将任务添加到JS runtine任务循环中,这是异步调用的原因,并且因为JS运行时的“运行完成”的基本原理确保onClick()在结束之前永远不会中断。
请注意,这很有趣,可能使代码难以理解...
function1
执行异步操作?