[javascript, jQuery] How to wait for an animation to complete before continuing another animation without callbacks

http://jsfiddle.net/jmztZ/

Above is a link to my problem. Let's say that I only have 1 div, the contents of which can be changed via .html (). I would like to use a div to change its contents and display itself using animation () or show (), etc. However, when there are 2 functions that control the div, the browser speed is too fast, which seems to skip the first .html ().

Question: How can I wait until the first function (otherwise "go ()" in the violin) fully executes (which includes changing the contents of .html () and the entire animation) before starting the second function (otherwise "went", )

Attempts:

Note. Even though my attempts seem to perform the animation accordingly in the queue, the html () function can never wait. Take a look at the violin again. In addition, I tried to find several methods in Stackoverflow, and they all match.

I tried using:

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

And using Deferred:

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

And also a self-named function:

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

But none of them work properly.

So, to finish, I would have an array that can use .push () to enter any number of functions to execute, all functions are related to managing the contents of the div and its animation. I would like to know how to correctly perform all the functions from this array one by one, and the next one should wait for the current to finish.

+4
source share
4 answers

Try it.

 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(); 

Here is the fiddle: http://jsfiddle.net/jmztZ/31/

+1
source

You cannot do this without a callback, but arround works here. When calling the function, send selfCall as a parameter:

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

Then in the go function do the following:

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

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

+1
source

I think you can try a technique called Monad . But what is a monad ? I cannot explain it properly.

So, "Please show me the code!"

We have some asynchronous functions in the pipequeue array, each function in the pipequeue must be a deferred instance. the function may be asynchronous. they will be executed one by one.

as follows: drop explode drop2 explode2 are four asynchronous animation processes, each of which returns a jQuery promise .

full code is in 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); 

You can push or pop pipequeue . every fn in pipequeue has no connection!

But if you think that pipe(unit(),pipequeue) little ...

you can wrap the unit() call in a function:

 function pipePromise(pipequeue){ pipe(unit(),pipequeue); } // then your call can be quite neat now pipePromise(pipequeue); 
0
source

I like Mr. Smee Answer , but there is another option. Write html in the callback .hide(0, callback) :

 $("#foo").hide(0, function(){ $(this).html("GO"); }); 

http://jsfiddle.net/jmztZ/34/

You can even call them as follows:

http://jsfiddle.net/jmztZ/35/

0
source

Source: https://habr.com/ru/post/1492527/


All Articles