在推送数据之前等待数组元素存在



我有这样的对象数组:

var arr = [{
'timestamp' : 1,
},{
'timestamp' : 2,
},{
'timestamp' : 3,
},{
...
}];

我使用计时器函数生成新对象并将其推送到arr的地方:

this.state.labelTimer = window.setInterval(function () {
addObjectToArr(timeStamp);
}, 1000);

事情变得有点毛茸茸的,因为我还有一个使用 Laravel Echo 的 WebSocket 实现,它可以修改arr中对象的属性:

// This method gets called whenever the WebSocket receives incoming data
Echo.channel('testChannel')
// we have detected incoming data
.listen('dataTrigger', (e) => {
// modify the object at some array index
modifyObjectInArr(e.data);
});

modifyObjectInArr(data(函数将一个属性附加到数组中的对象,如下所示:

arr[data.timestamp].someProperty = "something"

值得注意的是,我可以有多个请求进入相同的时间戳,导致对象如下所示:

var arr= [{
'timestamp' : 1,
'val_1' : 12, // originating from one websocket call
'val_2' : 13 // originating from another websocket call
}];

似乎有时,WebSocket 会尝试修改 arr[data.timestamp] 处的对象,然后再通过带有计时器的函数将元素推送到数组。有没有一种好方法可以等到数组在所需索引处有一个元素(我不能简单地检查它是否已经存在,如果不存在,请推送它 - 它必须由这个特定问题的计时器生成(,然后从 WebSocket 推送传入的数据?

您可以使用延迟实例化模式:

var arr = [];
function getDataFrame(timeStamp) {
// Gets existing or creates new object
return arr[timeStamp] || (arr[timeStamp] = { timestamp: timeStamp });
}
function modifyObjectInArr(data) {
getDataFrame(data.timestamp).someProperty = 'something';
}
this.state.labelTimer = window.setInterval(function () {
getDataFrame(timeStamp);
}, 1000);

这样,间隔回调或 Web 套接字回调是否首先尝试操作数据都没有争用条件。

我和一位同事构建了一些东西来解决类似的问题 - 在我们的例子中,我们想等到数组达到特定长度。 这主要用于测试(等到我们得到 X 事件然后检查它们(。

https://www.npmjs.com/package/awaitable-array

但它基本上是数组的替代品:

你可以创建一个"AwaitableArray((",并将你的项目推送到它并等待长度:

let arr = new AwaitableArray();
setInterval(() => arr.push("test"), 500);
// This waits until 2 items have been pushed to the array.
await arr.untilLength(2);

因此,您可以创建这个可等待的数组而不是常规数组,然后等到该索引被命中。

这是非常基本的 atm - 不支持 pop - 只是等待推送到该索引,但您可以非常轻松地扩展它以执行您需要的任何事情:

https://github.com/WakeskaterX/awaitable-array

它只是使用代理来拦截请求 - 我会对在高流量环境中使用它持怀疑态度,我不知道它可能对性能有什么影响,它只是我们的测试工具,但我们在这些情况下广泛使用它。

最新更新