Skip to content

Handling many and slow requests

JessicaOPRD edited this page Dec 28, 2022 · 5 revisions

Common scenarios

  • Suggestion/autocomplete searches — Last search term ('Rockaway Beach') is preferred over the earlier search term ('Ro'), but the less descriptive search often finishes after the more specific one and leads to inaccurate results. It's an accurate timing issue.

  • Pagination — Many similar requests are rapidly made, where the only difference is the pagination parameters. This can quickly overwhelm the stack. There can be bugs/problems across the implementation, but canceling the previous request is a good place to start on the client. Note in this scenario request cancellation is only guaranteed to relieve the work building up on the client. The server technology may or may not gracefully handle the request cancelation. It's a little unclear to me.

  • Long-running requests — This will happen for reasons that are sometimes beyond our control (slow or interrupted network). A spinner and/or skeleton loaders help indicate something is in progress or has gone wrong.

Client

One way I like to do this is to create a dedicated closure for the request at hand.

Note isLoading is a template variable used to globally display a search spinner.

You will need to request this closure/instance once at start-up and use it without creating a new one for all calls.

Closure

latestSearchRequest() {
  let call
  let timer = 0
  let intervalId

  return async (url, config = {}) => {
    if (call) {
      call.cancel()
    }

    if (timer > 0) {
      timer = 0
    }

    if (this.isLoading) {
      this.isLoading = false
    }

    if (intervalId) {
      clearInterval(intervalId)
    }

    call = axios.CancelToken.source()

    config.cancelToken = call.token

    intervalId = setInterval(() => {
      timer += 100

      if (timer > 200) {
        this.isLoading = true
      }
    }, 100)

    const request = await axios.get(url, config)

    clearInterval(intervalId)

    timer = 0

    if (this.isLoading) {
      this.isLoading = false
    }

    return request
  }
},

On data setup

latestSearch: vm.latestSearchRequest(),

Use

let { data } = await this.latestSearch('path/to/endpoint', {
  params: {
    method: 'getAll',
    ...search
  }
})