Вызов функции после завершения предыдущей функции

У меня есть следующий код JavaScript:

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable);
        function2(someOtherVariable);
    }
    else {
        doThis(someVariable);
    }
});

Как я могу гарантировать, что function2 вызывается только после завершения function1?

Ответ 1

Укажите анонимный обратный вызов и сделайте function1 его принятым:

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable, function() {
          function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});


function function1(param, callback) {
  ...do stuff
  callback();
} 

Ответ 2

Если вы используете 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/

Ответ 3

Попробуйте следующее:

function method1(){
   // some code

}

function method2(){
   // some code
}

$.ajax({
   url:method1(),
   success:function(){
   method2();
}
})

Ответ 4

В этом ответе используется promises, функция JavaScript стандарта ECMAScript 6. Если ваша целевая платформа не поддерживает 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 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
});

Ответ 5

Или вы можете инициировать настраиваемое событие, когда одна функция завершается, а затем привязать его к документу:

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 завершена.

Ответ 6

Это зависит от того, что делает функция.

Если функция1 выполняет некоторый простой синхронный javascript, например, обновляет значение div или что-то в этом роде, функция function2 срабатывает после завершения функции.

Если функция1 выполняет асинхронный вызов, такой как вызов AJAX, вам нужно будет создать метод "обратного вызова" (большинство API ajax имеют параметр функции обратного вызова). Затем вызовите функцию2 в обратном вызове. например:

function1()
{
  new AjaxCall(ajaxOptions, MyCallback);
}

function MyCallback(result)
{
  function2(result);
}

Ответ 7

Вы можете сделать это так

$.when(funtion1()).then(function(){
    funtion2();
})

Ответ 8

Если 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() никогда не прерывается до его завершения.

Обратите внимание, что это так забавно, как может быть трудно понять код...

Ответ 9

Если метод 1 должен быть выполнен после метода 2, 3, 4. Следующий фрагмент кода может быть решением для этого с использованием отложенного объекта в JavaScript.

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>