在Coffeescript中编写递归的setTimeout循环

时间:2012-03-08 20:06:59

标签: javascript jquery coffeescript

我正在制作一个实时照片流应用。基本上,用户将通过FTP将照片上传到我服务器上的文件夹,并且只要添加新照片而不刷新,页面就会更新。

我计划使用AJAX和此线程中建议的方法执行此操作:How to check if directory contents has changed with PHP?。基本上,我想在我的页面上每隔X秒进行一次循环,对一个PHP页面进行AJAX调用,该页面返回uploads文件夹目录列表的MD5哈希值。如果自上次调用后哈希值发生了变化,则另一个AJAX调用将获取最近添加的文件,jQuery将在页面上显示它。

在vanilla Javascript / jQuery中,这可以使用一个带有setTimeout的递归命名函数来完成。这段代码对我有用:

function refreshLoop(currentFolderState, refreshRate) {
    // Get the new folder state
    $.get("../ajax/getFolderState.php", function(data) {
        // If it's different than the current state
        if ( data !== currentFolderState ) {
            // Do something
        }
        // If it's the same as the current state
        else {
            // Do nothing
        }
        // After the refresh rate, try again
        setTimeout(function() {
            refreshLoop(data, refreshRate);
        }, refreshRate);
    });
}

// Document Ready
$(function() {

    var refreshRate = 5000;

    // After refresh rate has passed
    setTimeout(function() {
        // Get the starting folder state
        $.get("../ajax/getFolderState.php", function(data) {
            // Kick off the loop
            refreshLoop(data, refreshRate);
        });
    }, refreshRate);

});

我在这个项目中使用Coffeescript试图了解它是如何工作的,因为很多开发人员似乎都喜欢它,但我无法弄清楚如何在不使用命名函数的情况下复制这个功能。有人可以指出我正确的方向或为我解释一个更好的方法来实现这种效果,这可以很容易地在Coffeescript中完成吗?

4 个答案:

答案 0 :(得分:6)

更简洁的版本

do poll = ->
  #do work here
  setTimeout poll, 1000

编译为

var poll;
(poll = function() {
  //do work here
  return setTimeout(poll, 1000);
})();

答案 1 :(得分:4)

你可以在CoffeeScript中做这样的事情:

refresh_loop = (data, refresh_rate) ->
    #...etc

refresh_rate = 5000
setTimeout((->
    $.get("../ajax/getFolderState.php", (data) ->
        refresh_loop(data, refresh_rate)
), refresh_rate)

演示:http://jsfiddle.net/ambiguous/ZVTcg/

如果您的功能较小,那么您可以像这样内联所有内容:

refresh_rate = 5000
setTimeout(f = (->
    // real work goes here...
    setTimeout(f, refresh_rate)
), refresh_rate)

演示:http://jsfiddle.net/ambiguous/XThV6/

在你的情况下内联所有内容可能会有点难看和混乱,因此使用单独的refresh_loop = (data, refresh_rate) -> ...构造可能是一个更好的主意。

答案 2 :(得分:4)

我在这里看不到任何问题。您所要做的就是将refreshLoop分配给变量。这是您的代码直接转换为CoffeeScript:

    refreshLoop = (currentFolderState, refreshRate) ->
        $.get '../ajax/getFolderState.php', (date) ->
            # ...
            setTimeout (-> refreshLoop(data, refreshRate)), refreshRate

    $ ->
        refreshRate = 5000
        setTimeout (->
            $.get '../ajax/getFolderState.php', (data) ->
                refreshLoop data, refreshRate
        ), refreshRate

答案 3 :(得分:2)

  

但我无法弄清楚如何在不使用的情况下复制此功能   使用命名函数。

你可以使用这样的自调用匿名函数:

(function(){
   // do your stuff

   setTimeout(function(){
      arguments.callee();
   }, time);
})();

这里arguments.callee指的是匿名函数本身。

请注意,在ES5中不推荐使用arguments.callee,但使用命名函数没有任何问题。