我有以下JavaScript代码:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
如何确保函数2只在函数1完成后才被调用?
我有以下JavaScript代码:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
如何确保函数2只在函数1完成后才被调用?
当前回答
如果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运行任务循环中,这是异步调用所做的,并且因为JS运行时的“运行到完成”的基本原则确保onClick()在结束之前永远不会中断。
请注意,这很有趣,因为它使代码难以理解……
其他回答
这个答案使用了承诺,这是ECMAScript 6标准的一个JavaScript特性。如果您的目标平台不支持promise,请使用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指出的,$.ajax()返回的jqXHR对象实现了Promise接口。所以实际上没有必要把它包装在Promise中,它可以直接使用:
$.ajax(...params...).then(function(result) {
//whatever you want to do after the request
});
如果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运行任务循环中,这是异步调用所做的,并且因为JS运行时的“运行到完成”的基本原则确保onClick()在结束之前永远不会中断。
请注意,这很有趣,因为它使代码难以理解……
或者你可以在一个函数完成时触发一个自定义事件,然后将其绑定到文档:
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执行完毕时存在。
如果你正在使用jQuery 1.5,你可以使用新的延迟模式:
$('a.button').click(function(){
if(condition == 'true'){
$.when(function1()).then(function2());
}
else {
doThis(someVariable);
}
});
编辑:更新博客链接:
丽贝卡·墨菲在这里写了一篇很棒的文章:http://rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/
你可以这样做
$.when(funtion1()).then(function(){
funtion2();
})