通过用户输入

时间:2015-10-26 06:11:11

标签: javascript jquery promise jquery-deferred cancellation

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

我有这个功能。

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/

2 个答案:

答案 0 :(得分:1)

尝试使用.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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<button>stop m processes</button>
<div id="stage1">stage1</div>
<div id="stage2">stage2</div>

答案 1 :(得分:1)

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

这种解决方案完全不同。

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

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

animationend

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

尝试 here