【问题标题】:Mechanism of Recursive Callbacks递归回调机制
【发布时间】:2014-10-13 07:19:28
【问题描述】:

看到这个小提琴:http://jsfiddle.net/ym1aLk25/9/

var s = $('#shake');
var randomTran = function (flag) {
    flag = flag || 0;
    if (flag < 6) {
        var rh = Math.floor((Math.random() * 10) - 5),
            rv = Math.floor((Math.random() * 10) - 5);
        s.transit({x: rh,y: rv}, 50, randomTran.bind(this, ++flag))
    };
};
randomTran();
s.transit({x: 0,y: 0});

我试图让元素摇晃几秒钟,然后回到原来的位置。但它并没有像我预期的那样工作,问题出在回调函数上。根据这个问题:If a jQuery function calls itself in its completion callback, is that a recursive danger to the stack?,似乎回调仍在循环中,回调函数之后的代码也在执行。 那么除了设置超时之外,如何实现我的目标呢?我在哪里可以找到关于这个机制的更详细的解释?

【问题讨论】:

  • 你的函数中没有回调,它同时运行,因为 randomtran 异步运行
  • .transit 不是已经使用超时了吗?

标签: javascript recursion callback


【解决方案1】:

您的小提琴按预期工作,并且动画排队(如果.transit() 被重复调用多次,它们甚至会排队,因为插件使用 jQuery 的内部动画队列)。唯一的问题是 50 毫秒对于最多 5 个像素的动画来说太快了。我增加了时间并打印了计数器in this revision of your fiddle

看来,虽然回调还在循环,但回调函数后面的代码也在执行。

没有“循环回调”。回调传递returns before回调被调用的函数-调用.transit()的代码继续( ,在您的情况下,是 if 的结束 } 大括号、randomTran() 调用的结尾和 s.transit({x: 0,y: 0}); 初始化。

一旦这段代码执行完毕,其他代码就可以异步执行了。存储在某处的回调现在 - 将来,在 transit() 调用后 50 毫秒 - 被调用;确实开始另一个过渡,确实安排另一个回调,然后结束。

【讨论】:

  • 感谢您的解释,所以要让s.transit(0,0) 仅在其他转换之后执行,一种方法是识别队列并将s.transit(0,0) 推入其中,对吗?我也试过这个:jsfiddle.net/ym1aLk25/18,但这种行为对我来说就像一个谜......
  • 要么,但由于队列实际上是异步填充的(在每个单个动画之后,来自回调),这会很复杂。或者您只需在ifelse 部分执行s.transit(0, 0),即当您的flag 计数器达到限制时。
  • 我试图在 else 中执行它,但它并没有像我想象的那样成功。看到这个小提琴:jsfiddle.net/ym1aLk25/19
  • 由于某种原因,您的if 语句后有一个分号;,这导致您的else 出现语法错误。 Fixed here
【解决方案2】:

您的 randomTran 函数中没有回调,因此它异步运行。这意味着 randomtran() 开始,紧随其后的是 s.transit({x: 0,y: 0});被执行。

你可以运行 s.transit({x: 0,y: 0});在 randomTran 的回调中让它在其余部分之后执行:

var s = $('#shake');
var randomTran = function (flag,callback) {
    flag = flag || 0;
    if (flag < 6) {
        var rh = Math.floor((Math.random() * 10) - 5),
            rv = Math.floor((Math.random() * 10) - 5);
        s.transit({x: rh,y: rv}, 50, randomTran.bind(this, ++flag))
    }else{
      callback();
    }
};
randomTran(0,function(){ //0 is added because randomTran expects flag as first param
  s.transit({x: 0,y: 0}); //this will be executed after randomtran calls back, eg when flag=6
});

但是...恐怕你把事情复杂化了,我不确定你想要达到什么目标。

【讨论】:

  • 我想要达到的效果是这样的小提琴:jsfiddle.net/ym1aLk25/16 短暂晃动后,元素回到原来的位置。我知道这个解决方案,但我只是想更好地理解“回调”、“异步回调”等概念以及这种“递归回调”的工作原理。您上面的代码没有像我预期的那样工作,请参阅jsfiddle.net/ym1aLk25/17,摇动后,元素不会返回。我也试过这个:jsfiddle.net/ym1aLk25/18,但这种行为让我完全失去了理智......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-03
  • 2014-05-21
  • 2010-09-21
  • 1970-01-01
相关资源
最近更新 更多