Ferma jquery .questa catena tramite l’input dell’utente

Questa è probabilmente una domanda semplice, ma sono totalmente perso.

Ho questa funzione.

m.util.genericSwipeVertFunc = function ( ajaxRequest, swipeOutTarget, swipeInTarget ) { var stage1, stage2, failStage, dfd = $.Deferred(), finalStage, functionPromise; // Swipe of screen wait for ajax request stage1 = function () { return $.when( ajaxRequest, // Returns $.Deferred() m.util.animateDeffered(swipeOutTarget, "fadeOutDown", true) // Returns $.Deferred() ); }; // Swipe and Show stage2 = function () { swipeInTarget.show(); return m.util.animateDeffered(swipeInTarget, "fadeInDown"); // Returns $.Deferred() }; finalStage = function () { dfd.resolve(); } failStage = function () { console.log("fail!"); swipeInTarget.hide(); }; functionPromise = stage1() .then(stage2) .then(finalStage); $.when(functionPromise,dfd) .fail(failStage); return dfd; }; 

Fondamentalmente fa alcune animazioni fantasiose per sfumare in entrata e in uscita diversi output di risposta dalle funzioni ajax. Funziona tutto bene, tranne quando l’utente prova a passare da una destinazione all’altra molto velocemente (prima che una catena finisca di avviarne un’altra). Divento un’animazione folle dappertutto.

Voglio essere in grado di rifiutare la catena in qualsiasi momento facendo qualcosa di simile.

 // called on script load. var currentAction = $.Deferred(); // Called everytime someone starts animation chain. currentAction.reject(); currentAction = m.util.genericSwipeVertFunc(dfd, swipeOutTarget, swipeInTarget); ); 

Con il mio codice corrente, failFunction viene colpito correttamente ma non arresta l’esecuzione di stage2. Quindi si nasconde quindi lo mostra e continua a rompere le cose.

Quindi alla domanda. Come posso inserire un rinvio in una catena che posso rifiutare in qualsiasi momento durante l’esecuzione delle catene? 🙂


Esempio fiddle http://jsfiddle.net/ff3jojbo/


Aggiornamento per chiarimenti

Sto usando animate.css per le mie animazioni. Non animazione jquery. Sono più interessato a come interrompere la catena dall’avvio della fase successiva in qualsiasi momento dall’input dell’utente.


Risposta fiddle http://jsfiddle.net/aefkwa8a/

Prova a usare .queue() , .promise()

 // array of functions to add to queue var arr = []; var swipeInTarget = $("#stage1"); var swipeOutTarget = $("#stage2"); // pseudo `ajax` call var ajaxRequest = function ajaxRequest(next) { return $.Deferred(function(d) { setTimeout(function() { d.resolve("ajaxRequest") }, Math.random() * 5000) }).promise() // Note `.then(function() {console.log(this)})` for example , // can be removed .then(function(data) { console.log(data) }).then(next) } var stage1 = function stage1(next) { return swipeOutTarget.fadeTo(Math.random() * 5000, Math.random()) .promise() // Note `.then(function() {console.log(this)})` for example , // can be removed .then(function() { console.log(this) }) .then(next) } var stage2 = function stage2(next) { return swipeInTarget .show(Math.random() * 5000, function() { return $(this).fadeTo(Math.random() * 2000, Math.random()) }) .promise() // Note `.then(function() {console.log(this)})` for example , // can be removed .then(function() { console.log(this) }) .then(next) } // do stuff when queue cleared var failStage = function failStage() { return swipeInTarget.hide(Math.random() * 2000) .promise().then(function() { console.log("m processes stopped") }) } // always do stuff when queue cleared, // or all functions in queue complete var finalStage = function finalStage() { console.log("complete", this) } // create jQuery object var m = $({ m: arr }); // add function to `"stages"` queue m.queue("stages", [stage1, stage2, finalStage]); // do stuff when all functions complete , or queue cleared m.promise("stages") .then(finalStage); // dequque `"stages"` queue m.dequeue("stages"); // clear `"stages"` queue $("button").click(function() { m.queue("stages", []) .promise("stages").always(failStage) }) 
 #stage2 { display: none; } 
   
stage1
stage2

La soluzione di OP qui può fallire dopo diversi clic. In particolare, se si fa clic sul pulsante mentre una sezione sta volando, l’ultima sezione richiesta può entrare, quindi scomparire.

Questa soluzione è completamente diversa.

Invece di usare la coda / dequeue di jQuery, usa una normale catena di stage1().then(stage2) , e ferma il progresso lungo quella catena rimuovendo le classi di animazione CSS dall’elemento animato e staccando il suo gestore animationend , garantendo così la promise associata con il completamento non si risolve mai.

Come vedrete, gran parte delle funzionalità è considerata come plugin jQuery, il che rende la syntax comoda e compatta.

 $(function () { // ************************** // *** Various outer vars *** // ************************** var $sections = $('#TabSection>div').hide(); var ajaxPromise; var str = { //various strings 'animationend': 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', 'fadeOutClasses': 'fadeOutDown animated', 'fadeInClasses': 'fadeInDown animated', 'allClasses': 'fadeOutDown fadeInDown animated' }; // *********************************************** // *** Utilities in the form of jQuery plugins *** // *********************************************** jQuery.fn.killAnim = function(animation) { /* jQuery plugin : * Remove all the animation classs from all possible targets, and * detach any currently attached animationend handlers. * Depends on: str (object). */ return this.off(str.animationend).removeClass(str.allClasses); }; jQuery.fn.cssAnimate = function (animation) { /* jQuery plugin : * Perform CSS animation and return promise. * Depends on: str (object); killAnim (plugin). */ var that = this; return $.Deferred(function(dfd) { // if no target or target not visible, resolve; if(that.length == 0 || !that.is(':visible')) { dfd.resolve(); } that.addClass(animation).one(str.animationend, dfd.resolve); }).then(function() { that.killAnim(); }); }; jQuery.fn.genericSwipeVertFunc = function () { /* jQuery plugin : * Sequence two CSS animations - fadeOut then fadeIn. * Depends on: str (object); killAnim (plugin); cssAnimate (plugin). */ var that = this; // swipeInTarget var swipeOutTarget = $sections.filter(':visible()').eq(0); function stage1() { $sections.killAnim().not(swipeOutTarget).hide(); return swipeOutTarget.cssAnimate(str.fadeOutClasses).then(function() { swipeOutTarget.hide(); }); }; function stage2() { $sections.not(that).killAnim().hide(); return that.show().cssAnimate(str.fadeInClasses); }; return stage1().then(stage2); }; // ********************** // *** Event handlers *** // ********************** $('button').on('click', function (event) { var inTarget = $($(this).data('tar')); if(ajaxPromise) { ajaxPromise.abort('aborted'); } // *** start: emulate AJAX *** ajaxPromise = $.Deferred(function(dfrd) { setTimeout(dfrd.resolve, 1000); }); ajaxPromise.abort = ajaxPromise.reject; // *** end: emulate AJAX *** ajaxPromise.then(function() { return inTarget.genericSwipeVertFunc(); }).fail(function(e) { $sections.killAnim().hide(); console.log(e); }); }); }); 

Credo che questa soluzione sia più affidabile. Anche con un sacco di clic maniacali, non potevo sconfiggerlo.

Provalo qui