我可以在没有无限间隔或重新加载页面的情况下检测文件更改吗?

Can I detect a file change without an infinite interval or reloading the page?

我的问题基本上如下:我有一个网页 运行 另一个子域 (Airtime sourcefabric) 上的在线广播。现在我发现这个广播插件有一个很好的实时 API,所以我可以从这个 [=26] 访问 JSON 中的上一个、当前和下一首曲目(和显示)信息=]: http://music.wickedradionet.com/api/live-info .

我需要在网页上显示这些信息。我可以让它以 javascript 间隔工作,每秒更新 API URL 的信息(或每 5 秒,无所谓),但我认为必须有一个更好的方法。

有什么方法可以检查文件是否被更改,并且只有在信息不相同时才更新信息?我认为这可以通过一些棘手的 PHP 来完成,例如设置 CRON 作业,或者使用 WebSocket。有比在 JS 间隔中检查它更好的方法吗?

我现在用来更新的javascript:http://wickedradionet.com/js/wickedradio-playlist.js

下面介绍了两种改进轮询的方法:

1) 更高效AJAX轮询

与其每秒持续执行一个 ajax 请求(无论您是否获取数据),您可以创建一个与服务器的 hacky 开放连接,以便在请求完成后进行轮询,如下所示。 $.ajax() 调用的重要部分是 complete 选项。 timeout(即 30 秒)是为了确保在循环中断时继续轮询。

(function betterPoll(){
    $.ajax({ url: 'http://music.wickedradionet.com/api/live-info/', success: function (data) {
        // do something with "data"
    }, dataType: "json", complete: betterPoll, timeout: 30000 });
})();

2) WebSocket 连接

更好的选择是 WebSocket。这允许全双工、低延迟连接在客户端和服务器之间保持打开状态,从而实现 "real time" 通信。

如果您使用 Node.js,则 docs provide examples on how you can use Socket.IO for WebSocket communication. If you're using PHP, a quick search led me to Ratchet and PHP WebSockets

下面是一个使用 Socket.IO 的例子:

在你的 HTML:

<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script src="example.js"></script>

在"example.js"中,你可以有这样的东西:

var socket = io.connect('http://music.wickedradionet.com/api/live-info/');
socket.on('an event', function (data) {
  // do something with "data"
  socket.emit('another event', { other: 'data' });
});

在服务器上,您可以使用 .on('another event', function () {}).emit('an event', function () {}) 做类似的事情。

您知道文件更改的确切时间,即下一首歌曲开始的时间。您需要做的就是计算时间差来安排新的请求。

function stringToDate(s)  {
 s = s.split(/[-: ]/);
 return new Date(s[0], s[1]-1, s[2], s[3], s[4], s[5]*1);
};
function getPlaylistData() {
 $.ajax({
  dataType: "jsonp",
  url: "http://music.wickedradionet.com/api/live-info/",
  success: function (result) {
   /* Change your DOM, than calculate time for next request this way: */
   var requestTime = stringToDate( result.schedulerTime ).getTime() - result.timezoneOffset*1000;
   var nextChange = stringToDate( result.next.starts ).getTime();
   var differenceInMiliseconds = nextChange-requestTime;
   console.log( differenceInMiliseconds );
   setTimeout(getPlaylistData, differenceInMiliseconds);
  }
 });
};
$(document).on('ready', function () {
    getPlaylistData();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>