Rxjs timer is completing too early on react-native/android

300 Views Asked by At

Ok, in order to ask my question here's a little context:

I have a react-native project that uses the react-native-ble-plx library in order to access the device's bluetooth. The library has a startDeviceScan method that takes a callback, and so I wanted to use rxjs in order to scan for devices for a period of time and then collect them all in an array, returning the result as a promise. I'm doing this through a combination of bufferTime and take pipe operators, though I managed to do it with takeUntil(timer()) as well. This is the code for scanning(note: I'm using typescript as well):

  async lookForNearbyDevices(timeout = 5000): Promise<Device[]> {
    if (timeout < 1) {
      throw new Error('Erro: lookForNearbyDevices requer um timeout')
    }

    return new Promise<Device[]>((resolve, reject) => {
      const scanReader = new Observable<Device>(obs => {
        this.manager.startDeviceScan(
          [ServiceUUIDs],
          { allowDuplicates: false },
          (err, dvc) => {
            if (err) {
              obs.error(err)
              return
            } else if (!dvc) {
              // Unreachable code
              return
            }

            if (!protocolNameMatches(dvc.name)) {
              // not what I'm looking for
              return
            }

            obs.next(dvc)
          },
        )
      }).pipe(
        distinct(dvc => dvc.id),
        bufferTime(timeout),
        take(1),
      )

      let dvcs: Device[] = []
      scanReader.subscribe({
        next: result => (dvcs = result),
        error: err => {
          console.debug(err)
          reject(err)
        },
        complete: () => {
          this.manager.stopDeviceScan()
          resolve(dvcs)
        },
      })
    })
  }

The problem is that, when executing it on my device(Android 8.0), bufferTime(and even timer) is emitting ~2900ms too early, regardless of the value of timeout. This is a problem because I don't want to finish my scan too early; Right now I can "deal" with this by adding 3s to the timeout, but I'd rather figure out the underlying issue than to rely on this type of patchwork.

Trying to figure this out, I decided to try a minimalist example:

const obs = timer(6000)
console.time('timerRXJS')
obs.subscribe({
  complete() {
    console.timeEnd('timerRXJS')
  },
})

...and this example also completes about 2900ms too early.

Is there any reason that bufferTime(and timer) would emit early like that? Note that I haven't changed anything on rxjs Schedulers and whatnot, since I don't really understand how they work. Maybe there's something there to figure out?

Any help at all would be appreciated.

0

There are 0 best solutions below