2013-07-21 5 views
3

http://jsfiddle.net/jmztZ/[JavaScript, Jquery] Как ждать анимации, чтобы закончить полностью, прежде чем продолжить другую анимацию без обратных вызовов

Выше ссылка на мою проблему. Скажем, что у меня есть только 1 div, содержимое которых может измениться через .html(). Я хотел бы использовать div для изменения его содержимого и отображения самого себя с помощью анимации() или show() и т. Д. Однако, когда есть 2 функции, которые управляют div, скорость браузера слишком быстрая, что, кажется, пропускает первый .html ().

Вопрос: Как я могу дождаться, пока первая функция (ака «go()» в скрипке) полностью выполнится (что включает изменение содержимого .html() и всей анимации) перед тем, как запустить вторую функцию (иначе «).

Попытки:

Примечание: Даже если эти попытки мои, кажется, выполнить анимацию, соответственно, на очереди, функция HTML() никогда не может ждать. Взгляните на скрипку снова. Кроме того, я попытался найти несколько методов в Stackoverflow, и все они совпадают.

Я попытался с помощью:

//Regular way, obviously didn't work 
go(); went(); 

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

$.Deferred().done(go, went).resolve(); 

А также самостоятельно вызываемая функция:

var f = [go, went]; c = 0; 
(function selfCall(){ 
    if (c >= f.length) return; 
    f[c].call(); c++; 
    selfCall(); 
})(); 

Но никто из них не похоже на работу должным образом.

Итак, чтобы завершить работу, у меня будет массив, который может использовать .push() для запуска любого количества функций для выполнения, все функции связаны с управлением содержимым div и его анимацией. Я хотел бы знать, как правильно выполнять все функции из этого массива один за другим, а следующий должен ждать окончания текущего.

+0

Вы не можете сделать это без обратных вызовов. Так все работает. – Pointy

+0

@Pointy: Так есть ли способ обойти мою проблему? Как, в любом случае, чтобы вывести этот массив функций в обратные вызовы и заставить его работать? Я пробовал $ .Callbacks(), но это казалось неправильным. – cuzmAZN

+0

Есть способы сделать это, но он всегда включает в себя управление обратными вызовами. У вас может быть одна функция обратного вызова, которая выгружает элементы «рабочего списка» из массива (что в основном является тем, что делает jQuery для очереди анимации). – Pointy

ответ

1

Попробуйте это.

function go() { 
    $("#foo").html("GO"); 
    return $("#foo").show("drop", 750).hide("explode", 500).promise(); 
} 
function going() { 
    $("#foo").html("going"); 
    return $("#foo").show("drop", 750).hide("explode", 500).promise(); 
} 
function gone() { 
    $("#foo").html("gone"); 
    return $("#foo").show("drop", 750).hide("explode", 500).promise(); 
} 
function went() { 
    $("#foo").html("WENT"); 
    return $("#foo").show("drop", 750).hide("explode", 500).promise(); 
} 
var arr = [go, going, gone, went], 
    thisItem; 

//randomize array 
arr = arr.sort((function() { return 0.5 - Math.random();})); 

function getNextArrayFn() { 
    thisItem = arr.shift(); 
    thisItem().done(getNextArrayFn); 
}; 
getNextArrayFn(); 

Вот скрипка: http://jsfiddle.net/jmztZ/31/

+0

Этот технически использует обратные вызовы, которые я не предпочитаю. Спасибо за помощь. – cuzmAZN

+0

Просто из любопытства, почему бы вам не использовать обратные вызовы? –

+0

@cuzmAZN Ответ обновлен для работы без обратных вызовов. –

1

Вы не можете сделать это без обратного вызова, но вот работа arround. При вызове функции, отправить selfCall в качестве параметра:

f[c].call(null, selfCall); c++; //null = this in function, but you don't use this. 

Затем в функции идут, сделайте следующее:

function go(callback) { 
    $("#foo").html("GO"); 
    $("#foo").show("drop", 750).hide("explode", 500, callback); 
} 

Fiddle: http://jsfiddle.net/jmztZ/1/

0

Я думаю, вы можете попробовать технику под названием Монада - Но что Монада? Я не могу объяснить это правильно.

Итак, «Пожалуйста, покажите мне код!»

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

как это: dropexplodeexplode2drop2 четыре процесса асинхронной анимации, каждый из них вернулся через JQuery promise.

полный код на jsbin: http://jsbin.com/ikovof/2/

var $el = $("#foo"); 
function drop(){ 
    var defer = Deferred() 
    , promise = defer.promise() 
    $el.html("GO"); 
    $el.show("drop",{ 
    complete:function(){ 
     defer.resolve(); 
    } 
    },1000) 
    return promise; 
} 

function explode(){ 
    var defer = Deferred() 
    , promise = defer.promise() 
    $el.hide("explode",{ 
    complete:function(){ 
     defer.resolve(); 
    } 
    },1000) 
    return promise; 
} 

function drop2(){ 
    var defer = Deferred() 
    , promise = defer.promise() 
    $el.html("WENT"); 
    $el.show("drop",{ 
    complete:function(){ 
     defer.resolve(); 
    } 
    },1000) 
    return promise; 
} 

function explode2(){ 
    var defer = Deferred() 
    , promise = defer.promise() 
    $el.hide("explode",{ 
    complete:function(){ 
     defer.resolve(); 
    } 
    },1000) 
    return promise; 
} 

var pipequeue = [drop,explode,drop2] 

pipequeue.push(explode2); 

pipe(unit(),pipequeue); 

Вы можете push или poppipequeue. каждый Fn в pipequeue без связи

Но если вы думаете, pipe(unit(),pipequeue) это немного ...

вы можете обернуть unit() вызов в функцию:

function pipePromise(pipequeue){ 
    pipe(unit(),pipequeue); 
} 
// then your call can be quite neat now 
pipePromise(pipequeue); 
Смежные вопросы