使用foo.js和foo.js.coffee(空)的Rails资产管道导致JS循环。为什么?

时间:2012-07-09 14:41:15

标签: javascript ruby-on-rails coffeescript asset-pipeline sprockets

以下本身不是问题,因为可以通过不对两个资产管道文件使用相同的名称来避免这种情况。我只是对解释感到好奇,所以感谢任何见解。

这是Rails 3.2.6,链轮2.1.4(也尝试了最新的2.4.4)。一个最小的例子:http://github.com/richardkmichael/js-test

我有一个FooController,我正在写javascript而不是coffeescript,所以我创建了一个新文件foo.js,但是留空foo.js.coffee

我有一个setInterval()函数(测试readyState === 'complete'),它使用clearInterval()停止。但是,interval函数循环,好像clearInterval()调用不起作用。

当我删除空的foo.js.coffee文件时,循环停止并且JS按预期工作。替换空foo.js.coffee会再次启动客户端上的循环行为。

服务器端处理似乎正在更改某些客户端,导致重置/新间隔计时器?

这两种情况之间似乎没有客户端JS差异。但是,在Chrome的网络检查器中:

  • '资源'列出foo.js一次,在两种情况下都包含JS,因为它显示为foo.js服务器端。 application.js包含一个分号。 (除此之外,即使我删除了jQuery,这种循环行为仍然存在。)

  • '来源'(localhost / assets)列出foo.js?body=1两次。

app/controllers/foo_controller.rb

class FooController < ApplicationController
  def index
    render :inline => '<p>Hello, World!</p>', :layout => true
  end
end

app/assets/javascripts/foo.js

var readyStateCheckInterval = setInterval(function () {
  if (document.readyState === 'complete') {
    console.log('Document ready.');
    clearInterval(readyStateCheckInterval);
  }
}, 2000);

app/assets/javascripts/foo.js.coffee

<empty -- just `touch .../foo.js.coffee`>

一个(也许)类似的问题:sprockets duplicate file naming

更新

根据回复,我注意到有两个<script>标签(后见之明相当明显)。测试弗雷德里克的解释,我更改了javascript以避免丢失第一个计时器引用,并且按预期“正常工作”(正好是对console.log的两次写入)。

/*jslint indent: 2 */

(function () {

  'use strict';

  var intervalTimers = {},
    date = new Date(),
    time = date.getTime();

  function setupIntervalTimer(name) {
    intervalTimers[name] = setInterval(function () {
      if (document.readyState === 'complete') {
        console.log('Document ready.');
        clearInterval(intervalTimers[name]);
      }
    }, 2000);
  }

  setupIntervalTimer(time);

}());

1 个答案:

答案 0 :(得分:3)

您的Javascript被包含两次。网络检查员可能只显示一次,因为浏览器足够聪明,不能再次获取同一文件

当您的第一个Javascript副本运行时,它会创建您的计时器并将其值隐藏在readyStateCheckInterval中,以便以后可以取消它。第二个副本创建第二个计时器,并使用新值覆盖readyStateCheckInterval的值。你的回调然后最终尝试取消第二个计时器两次但从未取​​消第一个计时器(因为你现在已经失去了对它的引用)