2

I have a web application that received an update from websocket, like 100 messages per second.

I am using immutable helper and tried this

const parentIndex = action.payload.data.findIndex( i => i.id===action.id)
if(parentIndex !== -1) {
  const childIndex = action.payload.data[parentIndex].child.findIndex(c=>i.id===action.childId)
  if(child !== -1) {
     const lastChildIndex = action.payload.data[parentIndex].child[childIndex].lastChild.findIndex(l=>l.id===action.lastChildId)
     return lastChildIndex=== -1
     ? update(state, {   // insert
         data: {
           [parentIndex]: {
             child: {
               [childIndex]: {
                 lastChild: {
                   $push: [{
                      parentId: action.id,
                      childId: action.childId,
                      lastChildId: action.lastChildId,
                      price: action.payload.price
                   }]
                 }
               }
             }
           }
         }
       })
      : update(state, {   // update
         data: {
           [parentIndex]: {
             child: {
               [childIndex]: {
                 lastChild: {
                   [lastChildIndex]:{
                     price:  { $set: action.payload.price},
                     isUpdated: { $set: true}
                   }
                 }
               }
             }
           }
         }
       })
  }
}

Example Data:

data = [
  {
    parentId: 123,
    itemName: 'John Doe',
    child: {
      childId: 456,
      childName: 'I am child one',
      lastChild: {
        lastChildId: 789,
        price: 143  
      }
    }
  },
  {
    parentId: 321,
    itemName: 'John Wick',
    child: {
      childId: 654,
      childName: 'I am child wick',
      lastChild: {
        lastChildId: 987,
        price: 44  
      }
    }
  }
]

This seems to be work with 5 array of data at least but when the data is more than 15, the browser seem to be slow, memory leak and soon crashed..

Finding an index everytime there is a message that being pushed to the app will kill the browser.

I am using redux-thunk as middleware.

If you can recommend me something that will update/insert faster, better way and seamless. That would be super cool.

sinnede
  • 83
  • 7

3 Answers3

2

First address this:

a web application that received an update from websocket, like 100 messages per second

You should throttle or debounce these so you are not updating the state for every message. Or reduce the amount of messages if you can. Or both.

Once you get this out of the way, the app should probably work fine. But you could still make some improvements:

Given this action:

{
  payload: {
    parentId: 123,
    childId: 321,
    lastChildId: 555,
    price: 50
  }
}

Your reducer will look like this:

const { parentId, childId, lastChildId } = action.payload;
const childItem = state[parentId][childId][lastChildId];
const newState = {...state}
newState[parentId][childId][lastChildId] = {...childItem, ...action.payload};

return newState;

If I know I will need to be finding the specific item like you are doing here, I choose a map instead of an array.

Doug
  • 5,661
  • 2
  • 26
  • 27
  • by adding debounce or throttle in dispatch is it sure that I can cover or get all the messages? Like i'll debounce the action for a 100 milliseconds then there are 10 updates of that time. – sinnede Jun 05 '19 at 05:34
  • debounce only picks the last message in those 100 milliseconds. Throttle will process all messages but it will wait 100milliseconds between them. As @markerikson said above, you might want to batch them so you process a couple of them together. But to me it looks like there is a bigger problem on your design--do you really need to receive so many messages in such a short time and process all of them? – Doug Jun 05 '19 at 15:50
  • Yes, but there are times that the message is being push but nothing is updated and I would like to do is to filter the income message if it is needs to change the current state and if not, i'll do nothing. Do you think that even the action goes to reducer but it wont update the state will still save the performance? – sinnede Jun 05 '19 at 17:21
  • It depends on how many times you are preventing it from updating and how much performance you waste on checking if it should update or not. Dispatching an action is not that expensive, unless the payload is big or you do it extremely fast. How about not pushing this particular message from the backend if you don't need to update the state? Thats the approach I would take. – Doug Jun 05 '19 at 21:56
0

How about ditching arrays and making a store like this.

    {
     id: {
           childId:{...data,etc..},
           childId2:{},
           ... 
         },
     id2: {...},
     ...
    }

You can access ids with store.data[id].child[index]

In short that would be

if(store.data[parentIndex]&&store.data[parentIndex][childIndex]){
  !!!
}else{
  :(((
}
Aleks
  • 894
  • 10
  • 14
0

Three observations:

  • You probably don't need to be updating the UI 100 times per second. You should throttle or batch the websocket updates so that there's fewer updates to the state, and thus fewer updates to the UI.
  • Rather than using immutable-helper for immutable updates, I'd encourage you to use Immer. It's much simpler and easier to use. Even better, use our new Redux Starter Kit package, which has Immer built-in.
  • as @Aleks said, you should try to normalize your state shape so you aren't dealing with as much nested data.
Edgar
  • 6,022
  • 8
  • 33
  • 66
markerikson
  • 63,178
  • 10
  • 141
  • 157
  • I like the normalised state suggested in that link. I just think the `allIds: []` part is not necessary since you can derive that from the `byId` node. I also think `byId` might not be necessary, since when you see a map like this you can deduce the key is probably the ID of the entity... But I think its fine for clarity... – Doug Jun 04 '19 at 18:04
  • It's mostly useful if you want to maintain the original ordering and the IDs aren't numerically increasing. – markerikson Jun 04 '19 at 19:33