When developing a React and Firebase powered realtime chat app, a goal was to stretch the incoming messages so that each message is displayed 500ms after another exept the first message, which is displayed instantly. This ensueres readability as it flattens out peaks of incoming messages.

Second, Let's Take a Closer Look:

// timestamp when the last cued message will be displayedlet { nextTimestamp } =this.state// time nowconstnow=moment.now()
// time difference between now and the last cued message if any, else time difference is 0constdt= now - nextTimestamp <0? nextTimestamp - now :0// total of this batch is the number of incoming messages times our slomo constantconsttotalDelay= diff *SLOMO_DELAY_CONST// if there are no cued messages, time difference will be 0 and we just add the total delay to now.// else we want to add it to the current total delay:
nextTimestamp = dt ===0? now + totalDelay : nextTimestamp + totalDelay

Now that we got our variables straight, we can iterate over the number of incoming messages and set a timeout for each message before updating the state with the new message appended:

_.times(diff, i=> { // iterating over number of incoming messages// get the next slice of array conainting first new messageconstnext=_.take(messages, _.size(messages) - diff + i +1)
// if we have no cued messages, just update the stateif (dt ===0) {
this.setState({
messages: next
})
}
}
// else, update the next state with the according timeoutelse {
setTimeout(() => {
this.setState({
messages: next
})
}, dt +SLOMO_DELAY_CONST* (i +1)) // dt = current cued duration, i = current iteration
}
})
this.setState({
nextTimestamp // update timetamp for next batch
})

This is the first working version and surely can use some optimization but that's it for now :)

I also found another way: You could append all new messages with a "hidden" state option i.e. { ..., hidden: true} and run the delay algorithm against the hidden states and update them when timer is done. This would reduce memory as we wouldn't need to park the incoming messages in our timeout function.