我有以下JavaScript代码:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable);
function2(someOtherVariable);
}
else {
doThis(someVariable);
}
});
如何确保仅在function2
完成后调用function1
?
答案 0 :(得分:183)
指定一个匿名回调,并让make1接受它:
$('a.button').click(function(){
if (condition == 'true'){
function1(someVariable, function() {
function2(someOtherVariable);
});
}
else {
doThis(someVariable);
}
});
function function1(param, callback) {
...do stuff
callback();
}
答案 1 :(得分:89)
如果您使用的是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/
答案 2 :(得分:35)
试试这个:
function method1(){
// some code
}
function method2(){
// some code
}
$.ajax({
url:method1(),
success:function(){
method2();
}
})
答案 3 :(得分:34)
promises
,ECMAScript 6
标准的JavaScript功能。如果您的目标平台不支持promises
,请将其填充为PromiseJs。Promises是一种新的(并且更好)处理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 deferrds(从$.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
});
答案 4 :(得分:19)
或者,您可以在一个函数完成时触发自定义事件,然后将其绑定到文档:
function a() {
// first function code here
$(document).trigger('function_a_complete');
}
function b() {
// second function code here
}
$(document).bind('function_a_complete', b);
使用此方法,函数'b'只能执行AFTER函数'a',因为触发器仅在函数a执行完毕时存在。
答案 5 :(得分:3)
这取决于function1正在做什么。
如果function1正在做一些简单的同步javascript,比如更新一个div值,那么function2将在function1完成后触发。
如果function1正在进行异步调用,例如AJAX调用,则需要创建一个“回调”方法(大多数ajax API都有一个回调函数参数)。然后在回调中调用function2。例如:
function1()
{
new AjaxCall(ajaxOptions, MyCallback);
}
function MyCallback(result)
{
function2(result);
}
答案 6 :(得分:1)
您可以这样做
$.when(funtion1()).then(function(){
funtion2();
})
答案 7 :(得分:1)
如果方法1必须在方法2、3、4之后执行。下面的代码段可以是使用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>
答案 8 :(得分:0)
我遇到了这个问题。尽管使用上面的代码,但它无法正常工作。后来和其他人一起帮助我意识到我的第一个函数是异步的,第二个函数是同步的。
因此,尽管我编写了代码,异步函数仍在同步函数之后执行。
通过在第一个函数结束时调用第二个函数,我找到了一个解决方法。
答案 9 :(得分:0)
如果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()永远不会在结束之前被中断。
请注意,这很有趣,可能使代码难以理解...