I have an array of objects like such:
var arr = [{
'timestamp' : 1,
},{
'timestamp' : 2,
},{
'timestamp' : 3,
},{
...
}];
Where I generate and push new objects to arr with a timer function:
this.state.labelTimer = window.setInterval(function () {
addObjectToArr(timeStamp);
}, 1000);
Things get a little hairy, as I also have a WebSocket implementation using Laravel Echo that modifies properties of objects in 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);
});
And the modifyObjectInArr(data) function appends a property to an object in the array like such:
arr[data.timestamp].someProperty = "something"
It is worth noting that I can have multiple requests coming in for the same timestamp, resulting in objects that look like this:
var arr= [{
'timestamp' : 1,
'val_1' : 12, // originating from one websocket call
'val_2' : 13 // originating from another websocket call
}];
It seems that on occasion, the WebSocket will attempt to modify the objects at arr[data.timestamp] before the element is pushed to the array via the function with the timer. Is there a good way to wait until the array has an element at the desired index (I cannot simply check to see if it already exists, and if not, push it -- it must be generated by the timer in this particular problem) and then push the incoming data from the WebSocket?
You could use the lazy instantiation pattern:
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);
That way, there's no race condition whether the interval callbacks or web socket callbacks try to manipulate the data first.
A coworker and I built something to solve a similar problem - in our case we wanted to wait until an array had reached a specific length. This is mostly used for testing (wait until we get X events then check them).
https://www.npmjs.com/package/awaitable-array
But it's basically a replacement for an array:
You can create an "AwaitableArray()" instead and push your items to it and wait for length:
let arr = new AwaitableArray();
setInterval(() => arr.push("test"), 500);
// This waits until 2 items have been pushed to the array.
await arr.untilLength(2);
So you could create this awaitable array instead of a regular array and wait until that index is hit.
It's pretty basic atm - doesn't support pop - just waiting for pushes up to that index but you could extend it pretty easily to do just about anything you need:
https://github.com/WakeskaterX/awaitable-array
It just uses proxy to intercept requests - I'd be leery of using it in high traffic environments I do not know what performance impacts it might have it's been a testing tool only for us but we use this quite extensively for these kinds of situations.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.