通过用户输入来限制jquery .then链

这可能是一个简单的问题,但我完全迷失了。

我有这个function。

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; }; 

基本上它做了一些奇特的动画来淡入和淡出ajax函数的不同响应输出。 这一切都很好,除非用户试图非常快速地在目标之间进行切换(在一个链完成之前他们开始另一个)我在整个地方都得到了疯狂的动画。

我希望能够通过做这样的事情来随时拒绝链条。

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

使用我当前的代码,failFunction被正确命中,但它不会停止执行stage2。 所以它隐藏然后显示它并继续破坏事物。

所以问题。 如何在链执行期间的任何时候将延迟放在我可以拒绝的链中? 🙂


示例小提琴http://jsfiddle.net/ff3jojbo/


更新澄清

我正在使用animate.css来制作动画。 不是jquery动画。 我更感兴趣的是如何阻止链从用户输入的任何一点开始下一阶段。


回答小提琴http://jsfiddle.net/aefkwa8a/

尝试使用.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

只需点击几下,OP自己的解决方案就会失败。 特别是,如果在某个部分飞入时单击按钮,则最新请求的部分可能会飞入,然后消失。

这个解决方案完全不同。

它不使用jQuery的queue / dequeue,而是使用常规stage1().then(stage2) promise链,并通过从动画元素中删除CSS动画类并分离其animationend处理程序来停止向下进展,从而确保相关的承诺完成永远不会解决。

正如您将看到的,许多function都被视为jQuery插件,这使得方便,紧凑的语法。

 $(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 classes 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); }); }); }); 

我相信这个解决方案更可靠。 即使有很多狂躁的点击,我也无法击败它。

试试吧

Interesting Posts