多个 javascript 超时 - 实时数据获取问题
Posted
技术标签:
【中文标题】多个 javascript 超时 - 实时数据获取问题【英文标题】:Multiple javascript timeouts - problem with live data fetching 【发布时间】:2011-07-18 12:18:40 【问题描述】:我正在构建一个实时系统,该系统(使用 websockets)使用不同频率的实时数据更新表(可以是每秒 3 次,可以是每 2 秒一次 - 取决于数据类型) . 我目前正在努力寻找一种方法来让用户知道在过去 5 秒内何时未更新特定字段。也就是说,如果没有获取新数据,我不应该将旧值保留在那里,而是将其更改为“--”或类似的东西。
经过很长一段时间的javascript,更新字段的最终函数看起来像这样(非常简化):
function changeValue(data)
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
每次需要更改字段时都会调用此函数。我有 2 到 40 个不同的字段(取决于用户)被更改。
如果没有进行更新,设置计时器以每 5 秒将字段的值更改为“--”的最佳方法是什么?
我会非常感谢一些提示, 谢谢, 卡罗尔。
【问题讨论】:
创建一个对象,该对象将保存上次更新字段的时间。可能通过这种方式,您只需要 1 次超时 - 这是必须检查的最短时间。检查对象,并在必要时更新字段。 或者我不明白你的意思,或者你需要的是一个 var,比如 handler = setInterval(setTo'--;, 5000);,并在每个 changeValue 调用中清除/设置处理程序.是吗?看你说“更改字段的值”,然后说“更改字段的值”,所以我不知道你需要哪个。 【参考方案1】:由于您想在每个字段的基础上指示超时,您有两个明显的选择:
-
有一个全局间隔计时器,该计时器相当频繁地计时,并查看您的所有字段是否超时。
每个字段都有独立的计时器,只处理该字段。
我认为总的来说我更喜欢 (1) 到 (2),因为那时我们只处理一个间隔计时器,它使管理更简单。
由于文档中的 ID 必须是唯一的,我们可以使用您的字段 ID 值作为哈希(对象)中的键来存储上次更新时间。这是对先前答案的一种旋转,但适用于每个字段。以下是我们如何设置最后更新时间:
var lastUpdatedTimes = ;
function changeValue(data)
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
lastUpdatedTimes[fieldId] = new Date().getTime();
然后你设置一个间隔计时器来检查它们中的每一个。
function checkFieldsForTimeout()
var now = new Date.getTime();
// For each ID in lastUpdatedTimes, see if 'now minus
// last updated' is > 5000 and is so, set the field
// text to '--' and remove that entry from the last
// updated list with "delete lastUpdatedTimes[itemId]".
如果超时字段恢复活力,“--”将再次被一些真实文本替换。
每当我们将“--”放入字段时,通过从“lastUpdatedTimes”中删除最后更新时间,我们确保间隔计时器不会浪费时间处理已超时的字段。
【讨论】:
效果很好!简单的出色解决方案;)感谢一百万! 是否需要删除lastUpdatedTimes[itemId]?如果这样做,则需要先检查是否存在。 如果你不删除条目,那么下次在间隔计时器周围它会重新检查同一个条目,仍然认为它已经超时并再次用“--”更新它的文本不必要的。如果很多字段超时,它会浪费 CPU 时间,并且可能会在每个间隔滴答声中一遍又一遍地更新字段。当您使用“删除”时,您不需要先检查是否存在,但无论如何,它必须存在,因为您正在从迭代对象属性的循环中删除它。 . ...如果您担心如果删除项目,JS 引擎可能无法正确枚举所有属性,那么(1)您可能不在乎,因为间隔计时器无论如何都会很快再次运行,或(2)您可以将“lastUpdatedTimes”中的条目设置为“null”或其他一些神奇的无操作值,并在您的 checkFieldsForTimeout 属性枚举循环中检查它。 (2) 对我来说似乎很难看,尤其是考虑到 (1)。【参考方案2】:此答案已扩展以在@Andrew 发表评论后处理多个字段(另请参阅他的答案)。
在每个数据中引入一个属性updatedTime
,它保存数据最后一次更新的时间。定期计时器检查updatedTime
的所有数据并在适当时更新文本字段。检查的频率必须是检测周期的两倍。您的函数 changeValue()
会更新 updatedTime
和文本字段。
function checkData()
var now = new Date.getTime();
for "each data"
if (now - data.updatedTime >= 5000)
var fieldId = data.fieldId;
$('span#'+fieldId).text('--');
function changeValue(data)
var fieldId = data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
data.updatedTime = new Date.getTime();
// Install periodic timer to check last updates:
setInterval(checkData, 5000 / 2); // interval = half the required detection period
【讨论】:
我认为这行不通,即使忽略了“checkData()”中“数据”不可用的问题。 OP 似乎要求个别字段超时。在您的情况下,其中一个字段可能不会在十分钟内更新,但只要任何其他字段每秒都在更新,您的全局更新计时器就会不断变化。代码中的任何内容都不会返回到第一个停滞的字段并更新其值以指示特定于字段的超时。 是的,你说得对。我的答案只处理一个数据(我没有意识到需要多个数据)。对多个数据的扩展当然很简单。我赞成你的回答和你的评论。感谢您的评论!以上是关于多个 javascript 超时 - 实时数据获取问题的主要内容,如果未能解决你的问题,请参考以下文章
用 JavaScript 将网站后台的数据变化实时更新到前端
如何在实时 Firebase 数据库上侦听以通过后端 laravel 和 websocket 动态获取数据,而不使用 javascript