Подтвердить что ты не робот

Как я могу вызвать 3 функции для их выполнения один за другим?

Если мне нужно вызывать эти функции одну за другой,

$('#art1').animate({'width':'1000px'},1000);        
$('#art2').animate({'width':'1000px'},1000);        
$('#art3').animate({'width':'1000px'},1000);        

Я знаю, в jQuery я мог бы сделать что-то вроде:

$('#art1').animate({'width':'1000px'},1000,'linear',function(){
    $('#art2').animate({'width':'1000px'},1000,'linear',function(){
        $('#art3').animate({'width':'1000px'},1000);        
    });        
});        

Но давайте предположим, что я не использую jQuery и хочу позвонить:

some_3secs_function(some_value);        
some_5secs_function(some_value);        
some_8secs_function(some_value);        

Как мне следует вызывать эту функцию для выполнения some_3secs_function, и ПОСЛЕ того, как вызов заканчивается, затем выполнить some_5secs_function и ПОСЛЕ того, как вызов заканчивается, затем вызвать some_8secs_function?

UPDATE:

Это все еще не работает:

(function(callback){
    $('#art1').animate({'width':'1000px'},1000);
    callback();
})((function(callback2){
    $('#art2').animate({'width':'1000px'},1000);
    callback2();
})(function(){
    $('#art3').animate({'width':'1000px'},1000);
}));

Три анимации начинаются одновременно

Где моя ошибка?

4b9b3361

Ответ 1

В Javascript есть синхронные и асинхронные функции.

Синхронные функции

Большинство функций в Javascript являются синхронными. Если вы должны были вызвать несколько синхронных функций в строке

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

они будут выполняться по порядку. doSomethingElse не запускается до завершения doSomething. doSomethingUsefulThisTime, в свою очередь, не запустится до завершения doSomethingElse.

Асинхронные функции

Асинхронная функция, однако, не будет ждать друг друга. Давайте посмотрим на тот же самый пример кода, который у нас был выше, на этот раз, предполагая, что функции асинхронны

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

Функции будут инициализированы по порядку, но все они будут выполняться примерно в одно и то же время. Вы не можете последовательно предсказать, какой из них будет закончен первым: тот, который занимает наименьшее количество времени для выполнения, закончит сначала.

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

Callbacks

Предположим, что у нас есть три асинхронные функции, которые мы хотим выполнить по порядку, some_3secs_function, some_5secs_function и some_8secs_function.

Поскольку функции могут передаваться как аргументы в Javascript, вы можете передать функцию в качестве обратного вызова для выполнения после завершения функции.

Если мы создадим такие функции, как

function some_3secs_function(value, callback){
  //do stuff
  callback();
}

то вы можете вызвать его по порядку, например:

some_3secs_function(some_value, function() {
  some_5secs_function(other_value, function() {
    some_8secs_function(third_value, function() {
      //All three functions have completed, in order.
    });
  });
});

Таймауты

В Javascript вы можете указать функцию для выполнения после определенного таймаута (в миллисекундах). Фактически это может привести к синхронному функционированию синхронных функций.

Если у нас есть три синхронные функции, мы можем выполнить их асинхронно с помощью функции setTimeout.

setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);

Это, однако, немного уродливо и нарушает принцип DRY [wikipedia]. Мы могли бы немного почистить это, создав функцию, которая принимает массив функций и тайм-аут.

function executeAsynchronously(functions, timeout) {
  for(var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}

Это можно назвать так:

executeAsynchronously(
    [doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);

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

Ответ 2

В этом ответе используется promises, функция JavaScript стандарта ECMAScript 6. Если ваша целевая платформа не поддерживает promises, заполните его PromiseJs.

Посмотрите на мой ответ здесь Дождитесь завершения функции с анимацией, пока не запустите другую функцию, если хотите использовать анимацию jQuery.

Вот как будет выглядеть ваш код с ES6 Promises и jQuery animations.

Promise.resolve($('#art1').animate({ 'width': '1000px' }, 1000).promise()).then(function(){
    return Promise.resolve($('#art2').animate({ 'width': '1000px' }, 1000).promise());
}).then(function(){
    return Promise.resolve($('#art3').animate({ 'width': '1000px' }, 1000).promise());
});

Нормальные методы также могут быть помещены в Promises.

new Promise(function(fulfill, reject){
    //do something for 5 seconds
    fulfill(result);
}).then(function(result){
    return new Promise(function(fulfill, reject){
        //do something for 5 seconds
        fulfill(result);
    });
}).then(function(result){
    return new Promise(function(fulfill, reject){
        //do something for 8 seconds
        fulfill(result);
    });
}).then(function(result){
    //do something with the result
});

Метод then выполняется, как только закончится Promise. Обычно возвращаемое значение function, переданное в then, передается следующему как результат.

Но если возвращается Promise, следующая функция then ожидает завершения выполнения Promise и получает результаты его (значение, которое передается в fulfill).

Ответ 3

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

Код, который вы указали в своем обновлении, сразу же выполняет каждую из ваших функций обратного вызова, которые, в свою очередь, сразу же запускают анимацию. Анимации, однако, выполняются асинхронно. Он работает следующим образом:

  • Выполните шаг в анимации
  • Вызовите setTimeout с помощью функции, содержащей следующий шаг анимации и задержку
  • Проходит некоторое время
  • Обратный вызов setTimeout выполняет
  • Вернитесь к шагу 1

Это продолжается до тех пор, пока не завершится последний шаг анимации. Тем временем ваши синхронные функции уже давно завершены. Другими словами, ваш вызов функции animate не занимает 3 секунды. Эффект моделируется с задержками и обратными вызовами.

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

В простейшем случае это эквивалентно следующему:

window.setTimeout(function() {
    alert("!");
    // set another timeout once the first completes
    window.setTimeout(function() {
        alert("!!");
    }, 1000);
}, 3000); // longer, but first

Здесь имеется общая функция асинхронного цикла. Он будет вызывать данные функции в порядке, ожидая указанного количества секунд между ними.

function loop() {
    var args = arguments;
    if (args.length <= 0)
        return;
    (function chain(i) {
        if (i >= args.length || typeof args[i] !== 'function')
            return;
        window.setTimeout(function() {
            args[i]();
            chain(i + 1);
        }, 2000);
    })(0);
}    

Использование:

loop(
  function() { alert("sam"); }, 
  function() { alert("sue"); });

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

Ответ 4

Я полагаю, что библиотека async предоставит вам очень элегантный способ сделать это. В то время как promises и обратные вызовы могут немного затрудниться с juggle, async может дать аккуратные шаблоны, чтобы упростить ваш мыслительный процесс. Чтобы запускать функции в последовательном порядке, вам необходимо поместить их в async waterfall. В async lingo каждая функция называется task, которая принимает некоторые аргументы и a callback; которая является следующей функцией в последовательности. Основная структура будет выглядеть примерно так:

async.waterfall([
  // A list of functions
  function(callback){
      // Function no. 1 in sequence
      callback(null, arg);
  },
  function(arg, callback){
      // Function no. 2 in sequence
      callback(null);
  }
],    
function(err, results){
   // Optional final callback will get results for all prior functions
});

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

Ответ 5

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

function fone(callback){
...do something...
callback.apply(this,[]);

}

function ftwo(callback){
...do something...
callback.apply(this,[]);
}

тогда использование будет выглядеть следующим образом:

fone(function(){
  ftwo(function(){
   ..ftwo done...
  })
});

Ответ 6

asec=1000; 

setTimeout('some_3secs_function("somevalue")',asec*3);
setTimeout('some_5secs_function("somevalue")',asec*5);
setTimeout('some_8secs_function("somevalue")',asec*8);

Я не буду углубленно обсуждать setTimeout здесь, но:

  • В этом случае я добавил код для выполнения в виде строки. это самый простой способ передать var в вашу функцию setTimeout-ed, но пуристы будут жаловаться.
  • вы также можете передать имя функции без кавычек, но никакая переменная не может быть передана.
  • ваш код не дожидается запускает setTimeout.
  • Это может быть затруднительным, если вы сначала задумаетесь: из-за предыдущей точки, если вы передадите переменную из вашей вызывающей функции, эта переменная больше не будет существовать к моменту запуска триггеров таймаута - функция вызова будет иметь выполненный, и он исчез.
  • Я, как известно, использовал анонимные функции, чтобы обойти все это, но может быть лучший способ,

Ответ 7

Поскольку вы отметили его с помощью javascript, я бы пошел с таймером, так как ваши имена функций - 3, 5 и 8 секунд. Итак, запустите свой таймер, за 3 секунды, вызовите первый, 5 секунд в секунду, 8 секунд - в третьем, затем, когда это будет сделано, остановите таймер.

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

Ответ 8

//sample01
(function(_){_[0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this[1].bind(this))},
	function(){$('#art2').animate({'width':'10px'},100,this[2].bind(this))},
	function(){$('#art3').animate({'width':'10px'},100)},
])

//sample02
(function(_){_.next=function(){_[++_.i].apply(_,arguments)},_[_.i=0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this.next)},
	function(){$('#art2').animate({'width':'10px'},100,this.next)},
	function(){$('#art3').animate({'width':'10px'},100)},
]);

//sample03
(function(_){_.next=function(){return _[++_.i].bind(_)},_[_.i=0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this.next())},
	function(){$('#art2').animate({'width':'10px'},100,this.next())},
	function(){$('#art3').animate({'width':'10px'},100)},
]);

Ответ 9

Вы также можете использовать promises следующим образом:

    some_3secs_function(this.some_value).then(function(){
       some_5secs_function(this.some_other_value).then(function(){
          some_8secs_function(this.some_other_other_value);
       });
    });

Вам нужно будет сделать some_value глобальным, чтобы получить доступ к нему изнутри .then

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

    one(some_value).then(function(return_of_one){
       two(return_of_one).then(function(return_of_two){
          three(return_of_two);
       });
    });

Ответ 10

Я использую функцию waitUntil на основе javascript setTimeout

/*
    funcCond : function to call to check whether a condition is true
    readyAction : function to call when the condition was true
    checkInterval : interval to poll <optional>
    timeout : timeout until the setTimeout should stop polling (not 100% accurate. It was accurate enough for my code, but if you need exact milliseconds, please refrain from using Date <optional>
    timeoutfunc : function to call on timeout <optional>
*/
function waitUntil(funcCond, readyAction, checkInterval, timeout, timeoutfunc) {
    if (checkInterval == null) {
        checkInterval = 100; // checkinterval of 100ms by default
    }
    var start = +new Date(); // use the + to convert it to a number immediatly
    if (timeout == null) {
        timeout = Number.POSITIVE_INFINITY; // no timeout by default
    }
    var checkFunc = function() {
        var end = +new Date(); // rough timeout estimations by default

        if (end-start > timeout) {
            if (timeoutfunc){ // if timeout function was defined
                timeoutfunc(); // call timeout function
            }
        } else {
            if(funcCond()) { // if condition was met
                readyAction(); // perform ready action function
            } else {
                setTimeout(checkFunc, checkInterval); // else re-iterate
            }
        }
    };
    checkFunc(); // start check function initially
};

Это будет работать отлично, если ваши функции задают определенное условие true, которое вы могли бы опросить. Кроме того, он поставляется с таймаутами, которые предлагают вам альтернативы, если ваша функция не может что-то сделать (даже в течение определенного времени. Подумайте о обратной связи с пользователем!)

например,

doSomething();
waitUntil(function() { return doSomething_value===1;}, doSomethingElse);
waitUntil(function() { return doSomethingElse_value===1;}, doSomethingUseful);

Примечания

Дата вызывает приблизительные оценки таймаута. Для большей точности переключитесь на такие функции, как console.time(). Имейте в виду, что Date предлагает большую кросс-браузерную и устаревшую поддержку. Если вам не нужны точные миллисекундные измерения; не беспокойтесь или, наоборот, оберните его и предложите console.time(), когда браузер поддерживает его

Ответ 11

Если метод 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>