it-swarm-ru.tech

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

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

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

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

151
Rrryyyaaannn

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

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


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

Если вы используете jQuery 1.5, вы можете использовать новый шаблон Deferreds:

$('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/

86
philwinkle

В этом ответе используется 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
});
33
Domysee

Попробуй это :

function method1(){
   // some code

}

function method2(){
   // some code
}

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

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

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.

19
de Raad

Это зависит от того, что делает function1.

Если function1 выполняет какой-то простой синхронный javascript, такой как обновление значения div или чего-то еще, то function2 сработает после завершения function1.

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

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

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

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

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

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

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

0
StashOfCode

У меня была проблема с этим. Несмотря на использование приведенного выше кода, он не работал. Позже с помощью других я понял, что моя первая функция была асинхронной, а вторая - синхронной. 

Следовательно, асинхронный выполнялся после синхронной функции, несмотря на код, который я написал.

Я нашел обходной путь в моем случае, вызвав вторую функцию в конце моей первой функции.

0
Rahul Makhija