0

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.

Badashi
  • 1,124
  • 9
  • 18
  • 1
    if timer doesn't specify specific scheduler, it'll use asyncscheduler as default scheduler. couple of q: 1. what happens if you use different scheduler? 2. in those devices, what's result if you do plain scheduling via `setInterval`? – OJ Kwon Sep 27 '18 at 04:31
  • When using `setInterval`, the *first* timer completes early(~2600ms), while subsequent timers complete normally. Meanwhile, if I use chained `setTimeout`s, *every* timeout completes early. This issue also doesn't occur on iPhone, for the record. Seems like setTimeout has a problem on my device? I'll look into it, thanks for the direction – Badashi Sep 27 '18 at 13:49

0 Answers0