我有一个像这样的对象数组:
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
它只是使用代理来拦截请求 - 我对在高流量环境中使用它持怀疑态度我不知道它可能对它有什么性能影响它只是我们的测试工具,但我们在这些情况下使用它非常广泛。