1

Currently I'm working inside a chat application using webSockets. I've implemented a indicator which shows that one of the chat members is currently typing. I have another call which fires 5 seconds after the person starts typing to remove the indicator. The problem I'm having is that if the person continues to type longer than 5 seconds then the 'typing' indicator flashes in and out rapidly in the UI... Here is my current implementation.

sendChatState({ commit, dispatch, state }, payload) {
    connectionService.connection.setDialogChatState({dialogId: payload.visitId, conversationId: payload.visitId, chatState: 'composing'})
    // Create set timeout here to pause typing indicator...
    setTimeout(() => {
    connectionService.connection.setDialogChatState({dialogId: payload.visitId, conversationId: payload.visitId, chatState: 'pause'})
    }, 5000)
  },

Appears I may need to use some type of throttle to limit the amount of calls. However this is where I'm having trouble as I'm not entirely sure how to implement this.

LDB
  • 543
  • 4
  • 13
  • 29
  • Possible duplicate of [Vuetify : throttle / debounce v-autocomplete](https://stackoverflow.com/questions/56821337/vuetify-throttle-debounce-v-autocomplete) – tony19 Aug 06 '19 at 21:04

2 Answers2

0

You can solve it using debounce from lodash. Doing:

_.debounce(callServiceMethod, delay_time, { 'leading': true })

The debounce function is sending you back a throttled version of the function when you are calling it. In order to access it from the component scope and in the template within an eventHandler, the easiest way would be something like this:

import debounce from 'lodash/debounce'

export default {
  ...,
  methods: {
    sendChatState: debounce(function() {
            do your thing here 
    }, delay_time, { 'leading': true }),
  },
  ...
}

Note you need to use the config parameter to immediate call the method.

More info here.

GeorgesA
  • 320
  • 2
  • 9
Matheus Valenza
  • 889
  • 1
  • 5
  • 11
  • Ive tried this and wrapping it around the setDialogChatState() call... However I get an error stating 'debounce expects a function'. – LDB Aug 06 '19 at 17:26
  • Actually you should not execute the method like setDialogChatState(). Instead of it, you should put setDialogChatState – Matheus Valenza Aug 06 '19 at 19:22
0

Let's set the flag typing to FALSE at the beginning. On each change of the input value (meaning there is typing) you start a timer (and first cancel the previous timer, if there was an active one) and if the flag typing was FALSE - set it to TRUE and show the indicator (otherwise it has already been shown). Once the timer fires - you hide the indicator and set the flag typing to FALSE.

<template>
  <textarea v-model="message" @input="setFlag"/>
</template>

<script>
...
data()
{
  return {
    message: '',
    typing: false,
    timer: null,
  }
},
beforeDestroy()
{
  if (this.timer) clearTimeout(this.timer);
},
methods:
{
  setFlag()
  {
    if (this.timer) clearTimeout(this.timer);
    this.timer = setTimeout(this.timeOut, 5000);
    if (!this.typing)
    {
      this.typing = true;
      connectionService.connection.setDialogChatState({dialogId: payload.visitId, conversationId: payload.visitId, chatState: 'composing'});
    }
  },
  timeOut()
  {
    this.typing = false;
    connectionService.connection.setDialogChatState({dialogId: payload.visitId, conversationId: payload.visitId, chatState: 'pause'});
    this.timer = null;
  }
}
</script>
IVO GELOV
  • 13,496
  • 1
  • 17
  • 26