等待数组元素存在,然后再推送数据

时间:2018-06-20 23:32:26

标签: javascript

我有一个像这样的对象数组:

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推送传入的数据?

2 个答案:

答案 0 :(得分:2)

您可以使用惰性实例化模式:

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套接字回调首先尝试操纵数据就没有竞争条件。

答案 1 :(得分:0)

我和我的同事构建了一些东西来解决类似的问题-在我们的例子中,我们想等到数组达到特定长度。这主要用于测试(等到我们得到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

它仅使用代理来拦截请求-我不愿意在高流量环境中使用它,我不知道它仅对我们来说是一种测试工具,但可能会对性能产生什么影响,但是我们在此类中广泛使用了它情况。