在 Javascript 中以一定速度循环遍历数组
Loop through array at certain speed in Javascript
我是新来的所以请放过我。
我正在做我的一个小爱好项目,其中一个应用程序收集遥测数据,该遥测数据以 60Hz 的频率记录和保存(因此数组中每秒有 60 个索引)。总是这样。
然后我想 'play through' 这个阵列以正常速度播放,就像您正在播放视频一样。但是我不想看视频,而是想在前端显示您所在的每个索引的当前数据。
数组的结构还没有建立,但我想我会在数据库的某个地方存储和加载一个 JSON 文件。然后应该在我的前端播放。我已经使用 Angular (6) 来构建它,所以如果它可以与 Angular 混合使用会很棒(以跟踪您现在所在索引的进度,并绑定值当前索引的前端)。
indexx 只使用 0-1-2-etc 或类似时间戳之类的东西会容易吗?
欢迎提出任何建议。这里最重要的是保持快速,这样你就不需要强大的装备来玩这个。
提前致谢!
您需要使用 setInterval
函数,在该函数中您将根据频率遍历数组。因此,如果您的频率是 60hz
,这意味着您希望每 1000 / 60
毫秒
后迭代到数组中的下一个元素
var data = [1, 2, 3, 4, 5]
var currentIndex = 0;
var interval = 1000 / 60
var id = setInterval(function() {
// do your thing
if(currentIndex == (data.length-1)) {
clearInterval(id)
} else {
currentIndex++
}
}, interval)
这不是对数组的特别迭代,而是在一段时间间隔后执行一些操作,然后移动到下一个项目,当您完成数组时,这将清除间隔。也许链表在这里比数组更有帮助
你可以让自己成为这些事情的简单跑步者。它基本上是一个游戏引擎,你需要一个游戏循环:)
这是一个天真的例子。为了 brewity,这里跳过大部分错误检查和验证。
class TelemetryPlayer {
constructor(items, render, interval) {
// setup local data.
this.interval = interval;
this.items = items;
this.render = render;
this.startLoop();
}
// Loop simply initializes before the first run, and then runs the loop.
// Other places do the actual work.
startLoop() {
this._renderInProgress = false;
this._currentIndex = 0;
// save the interval reference if you wanna pause/reset later on.
this._interval = setInterval(this.doWork.bind(this), this.interval);
}
// here we perform the actual render.
doWork() {
if (this._renderInProgress) {
// previous render has not completed yet.
console.log('skip');
return;
}
console.log('Tick');
this._renderInProgress = true;
const item = this.items[this._currentIndex];
console.log('Tick');
// now, call your renderer, and update stuff when complete.
this.render(item)
.then(() => {
// Or this can be a callback or similar.
this._renderInProgress = false;
// Ready next item. Do not go out of array bounds.
this._currentIndex++;
if (this._currentIndex === this.items.length) {
this._currentIndex = 0;
}
});
}
// You can then add fun things like skip, pause, reset etc.
skip(item) {
if (item < 0 || item > this.items.length) {
return;
}
// pause first
this.pause();
this._currentIndex = item;
this.unpause();
}
//
reset() {
this.skip(0);
}
//
pause() {
this._interval = clearInterval(this._interval);
}
unpause() {
if (!this._interval) {
this._interval = setInterval(this.doWork.bind(this), this.interval);
}
}
// you can even add items later
addItem(item) {
this.items.push(item);
}
// or replace them.
replaceItem(item, index) {
this.items[index] = item;
// show the new item right away.
this.skip(index);
}
// or add an item to be played just once.
playOnce(item) {
this.pause();
this.render(item);
this.unpause();
}
}
下面是一个用法示例。您可以复制代码(上面的 class 和下面的代码块)并将其粘贴到 Whosebug 上的控制台中,以查看它的工作情况。你可能想做其他事情,但你会明白要点的。
let items = [ 100, 200, 300, 50, 100, 200, 300, 250 ];
const timeline = document.createElement('ul');
// maybe better do this by adding class and external stylesheet
timeline.setAttribute('style', 'padding: 15px; border: 1px solid gray; list-style-type: none; height: 500px; width: 100%; position: absolute; top: 0;overflow-y: scroll;')
document.body.appendChild(timeline);
let render = function(item) {
return new Promise(function (resolve) {
// run something (in) expensive with item now.
const li = document.createElement('li');
// again, better do this with class.
li.setAttribute('style', `display: inline-block; width: 25px; margin: 5px; background-color: #c1c1c1; height: ${item}px;`);
timeline.appendChild(li);
li.scrollIntoView();
// return when done.
resolve();
});
}
const player = new TelemetryPlayer(items, render, 1500);
// now you can do things like speed up etc.
// now you can do things like speed up etc.
function speedUp() {
// speedup 3 seconds after "playback" starts.
return new Promise((resolve) => setTimeout(() => {
player.pause();
player.interval = 600;
player.unpause();
resolve();
}, 3000));
}
function playOnce() {
// add item once, but not in the array we loop around in
return new Promise((resolve) => setTimeout(() => {
player.playOnce(1000);
resolve();
}, 3000));
}
// or add a few items that will be repeated.
function addItems() {
// add a super very high item 3 seconds after function call.
return new Promise((resolve) => setTimeout(() => {
player.pause();
player.addItem(400);
player.addItem(430);
player.addItem(420);
player.unpause();
// now rewind to this block. I am off by one, likely.
player.skipTo(player.items.length - 3);
resolve();
}, 5000))
}
speedUp()
.then(playOnce)
.then(addItems);
我是新来的所以请放过我。
我正在做我的一个小爱好项目,其中一个应用程序收集遥测数据,该遥测数据以 60Hz 的频率记录和保存(因此数组中每秒有 60 个索引)。总是这样。
然后我想 'play through' 这个阵列以正常速度播放,就像您正在播放视频一样。但是我不想看视频,而是想在前端显示您所在的每个索引的当前数据。
数组的结构还没有建立,但我想我会在数据库的某个地方存储和加载一个 JSON 文件。然后应该在我的前端播放。我已经使用 Angular (6) 来构建它,所以如果它可以与 Angular 混合使用会很棒(以跟踪您现在所在索引的进度,并绑定值当前索引的前端)。
indexx 只使用 0-1-2-etc 或类似时间戳之类的东西会容易吗?
欢迎提出任何建议。这里最重要的是保持快速,这样你就不需要强大的装备来玩这个。
提前致谢!
您需要使用 setInterval
函数,在该函数中您将根据频率遍历数组。因此,如果您的频率是 60hz
,这意味着您希望每 1000 / 60
毫秒
var data = [1, 2, 3, 4, 5]
var currentIndex = 0;
var interval = 1000 / 60
var id = setInterval(function() {
// do your thing
if(currentIndex == (data.length-1)) {
clearInterval(id)
} else {
currentIndex++
}
}, interval)
这不是对数组的特别迭代,而是在一段时间间隔后执行一些操作,然后移动到下一个项目,当您完成数组时,这将清除间隔。也许链表在这里比数组更有帮助
你可以让自己成为这些事情的简单跑步者。它基本上是一个游戏引擎,你需要一个游戏循环:)
这是一个天真的例子。为了 brewity,这里跳过大部分错误检查和验证。
class TelemetryPlayer {
constructor(items, render, interval) {
// setup local data.
this.interval = interval;
this.items = items;
this.render = render;
this.startLoop();
}
// Loop simply initializes before the first run, and then runs the loop.
// Other places do the actual work.
startLoop() {
this._renderInProgress = false;
this._currentIndex = 0;
// save the interval reference if you wanna pause/reset later on.
this._interval = setInterval(this.doWork.bind(this), this.interval);
}
// here we perform the actual render.
doWork() {
if (this._renderInProgress) {
// previous render has not completed yet.
console.log('skip');
return;
}
console.log('Tick');
this._renderInProgress = true;
const item = this.items[this._currentIndex];
console.log('Tick');
// now, call your renderer, and update stuff when complete.
this.render(item)
.then(() => {
// Or this can be a callback or similar.
this._renderInProgress = false;
// Ready next item. Do not go out of array bounds.
this._currentIndex++;
if (this._currentIndex === this.items.length) {
this._currentIndex = 0;
}
});
}
// You can then add fun things like skip, pause, reset etc.
skip(item) {
if (item < 0 || item > this.items.length) {
return;
}
// pause first
this.pause();
this._currentIndex = item;
this.unpause();
}
//
reset() {
this.skip(0);
}
//
pause() {
this._interval = clearInterval(this._interval);
}
unpause() {
if (!this._interval) {
this._interval = setInterval(this.doWork.bind(this), this.interval);
}
}
// you can even add items later
addItem(item) {
this.items.push(item);
}
// or replace them.
replaceItem(item, index) {
this.items[index] = item;
// show the new item right away.
this.skip(index);
}
// or add an item to be played just once.
playOnce(item) {
this.pause();
this.render(item);
this.unpause();
}
}
下面是一个用法示例。您可以复制代码(上面的 class 和下面的代码块)并将其粘贴到 Whosebug 上的控制台中,以查看它的工作情况。你可能想做其他事情,但你会明白要点的。
let items = [ 100, 200, 300, 50, 100, 200, 300, 250 ];
const timeline = document.createElement('ul');
// maybe better do this by adding class and external stylesheet
timeline.setAttribute('style', 'padding: 15px; border: 1px solid gray; list-style-type: none; height: 500px; width: 100%; position: absolute; top: 0;overflow-y: scroll;')
document.body.appendChild(timeline);
let render = function(item) {
return new Promise(function (resolve) {
// run something (in) expensive with item now.
const li = document.createElement('li');
// again, better do this with class.
li.setAttribute('style', `display: inline-block; width: 25px; margin: 5px; background-color: #c1c1c1; height: ${item}px;`);
timeline.appendChild(li);
li.scrollIntoView();
// return when done.
resolve();
});
}
const player = new TelemetryPlayer(items, render, 1500);
// now you can do things like speed up etc.
// now you can do things like speed up etc.
function speedUp() {
// speedup 3 seconds after "playback" starts.
return new Promise((resolve) => setTimeout(() => {
player.pause();
player.interval = 600;
player.unpause();
resolve();
}, 3000));
}
function playOnce() {
// add item once, but not in the array we loop around in
return new Promise((resolve) => setTimeout(() => {
player.playOnce(1000);
resolve();
}, 3000));
}
// or add a few items that will be repeated.
function addItems() {
// add a super very high item 3 seconds after function call.
return new Promise((resolve) => setTimeout(() => {
player.pause();
player.addItem(400);
player.addItem(430);
player.addItem(420);
player.unpause();
// now rewind to this block. I am off by one, likely.
player.skipTo(player.items.length - 3);
resolve();
}, 5000))
}
speedUp()
.then(playOnce)
.then(addItems);