Проблема с обработкой асинхронной функции в функции прослушивателя компонента Bluetooth manager

#javascript #react-native #promise #bluetooth-lowenergy #react-native-ble-plx

#javascript #react-native #обещание #bluetooth — низкое энергопотребление #react-native-ble-plx

Вопрос:

У меня возникли проблемы с запуском некоторого асинхронного кода в приложении Bluetooth RN.

Я пытаюсь создать функцию прослушивателя, которая выполняет следующее: подключаюсь к устройству (используя асинхронную функцию), регистрирую, что я подключился, затем отключаюсь от устройства (используя асинхронную функцию).

Эта функция прослушивания предоставляется в качестве параметра функции сканирования устройств Bluetooth с низким энергопотреблением (ble):

 // Relevant Function Prototypes --------------------------------------------------

// startDeviceScan() -> This scans for devices and runs a listener function on each
//                      device it scans. 
bleManager.startDeviceScan(
  UUIDs: ?Array<UUID>,
  options: ?ScanOptions,
  listener: (error: ?Error, scannedDevice: ?Device) => void // <- this listener function
)
// connectToDevice() -> This connects to a device scanned by the bleManager in the 
//                      listener function given to startDeviceScan()
bleManager.connectToDevice(
  deviceIdentifier: DeviceId,
  options: ?ConnectionOptions,
): Promise<Device>

// My code ------------------------------------------------------------------------

// Scans nearby ble devices advertising and runs a listener function that has the 
//  connection error status and device id as given parameters.
// **This function triggers on a Button onPress
 const handleStartScanning = async () => {
        try {
            bleManager.startDeviceScan(
                ['00001200-0000-1000-8000-00805f9b34fb'], // the service UUID I am scanning for
                { allowDuplicates: true }, // I allow to duplicates to continuously reconnect to devices
                async (error, device) => {

                    // get services
                    let services = device.serviceUUIDs // get list of the service UUIDs on device

                    // make sure services not null and out service UUID is included
                    if (services amp;amp; services.includes('00001200-0000-1000-8000-00805f9b34fb')) {

                        // log the scanned device's name, rssi, and its service UUIDs                        
                        console.log("Scanned a device with name: "   device.name   " | "   device.rssi)
                        console.log("Services:", services)
                        await bleManager.connectToDevice(device.id) // <- *****ISSUE HERE*****
                        console.log("Connected to device") // <- *****THIS NEVER PRINTS*****
                        // run some more async code here once i'm connected to the device
                        await bleManager.cancelDeviceConnection(device.id)
                    }
                }
            )
        } catch (error) {
            console.log('Could not start scanning for devices', { error })
        }
    }
  

Я не понимаю, почему, хотя я сделал функцию прослушивателя асинхронной и ожидал 2 асинхронных вызова функции в прослушивателе, Connected to Device журнал никогда не печатается. Это означает, что прослушиватель никогда не выполняется после await bleManager.connectToDevice(device.id) вызова асинхронной функции

Вот мой журнал консоли:

Обратите внимание, что Possible Unhandled Promise Rejection (id: 150): BleError: Operation was cancelled ошибка типа регистрируется повторно после фрагмента, который я опубликовал ниже. Иногда журнал возвращается к сканированию на некоторых устройствах, но всегда возвращается к отклонениям обещаний. Connected to device Консоль.журнал никогда не печатается.

 [Thu Oct 01 2020 22:59:42.385]  LOG      Scanned a device with name: Android | -43
[Thu Oct 01 2020 22:59:42.387]  LOG      Services: ["00001200-0000-1000-8000-00805f9b34fb"]
[Thu Oct 01 2020 22:59:42.388]  LOG      Scanned a device with name: Android | -43
[Thu Oct 01 2020 22:59:42.388]  LOG      Services: ["00001200-0000-1000-8000-00805f9b34fb"]
[Thu Oct 01 2020 22:59:42.487]  LOG      Scanned a device with name: Android | -44
[Thu Oct 01 2020 22:59:42.491]  LOG      Services: ["00001200-0000-1000-8000-00805f9b34fb"]
[Thu Oct 01 2020 22:59:42.492]  LOG      Scanned a device with name: Android | -44
[Thu Oct 01 2020 22:59:42.492]  LOG      Services: ["00001200-0000-1000-8000-00805f9b34fb"]
[Thu Oct 01 2020 22:59:42.514]  WARN     Possible Unhandled Promise Rejection (id: 150):
BleError: Operation was cancelled
construct@[native code]
_construct@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:23889:28
Wrapper@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:23844:25
construct@[native code]
_createSuperInternal@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:117317:322
BleError@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:117330:26
parseBleError@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:117368:30
_callPromise$@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:117632:51
tryCatch@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:24712:23
invoke@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:24885:32
tryCatch@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:24712:23
invoke@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:24785:30
http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:24797:21
tryCallOne@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:26784:16
http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:26885:27
_callTimer@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:30324:17
_callImmediatesPass@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:30363:17
callImmediates@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:30580:33
__callImmediates@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:2630:35
http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:2416:34
__guard@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:2613:15
flushedQueue@http://10.0.0.122:8081/index.bundle?platform=iosamp;dev=trueamp;minify=false:2415:21
flushedQueue@[native code]
invokeCallbackAndReturnFlushedQueue@[native code]
  

ОБНОВЛЕНИЕ РЕШЕНИЯ:
Большое спасибо Jaromanda X за предоставленное решение!

Исправление состояло в том, чтобы добавить перехваты попыток вокруг асинхронных функций connectToDevice () и cancelDeviceConnection (), поскольку они отклонялись, и слушатель возвращался (следовательно, почему журнал «Подключен к устройству» никогда не печатался).

 bleManager.startDeviceScan(
                ['00001200-0000-1000-8000-00805f9b34fb'],
                { allowDuplicates: true },
                async (error, device) => {
                    // get services
                    let services = device.serviceUUIDs
                    // check if there are services being advertised
                    if (services amp;amp; services.includes('00001200-0000-1000-8000-00805f9b34fb')) {
                        console.log("Scanned a device with name: "   device.name   " | "   device.rssi)
                        console.log("Services:", services)
                        try {
                            await bleManager.connectToDevice(device.id)
                        } catch {
                            console.log("Could not connect")
                        }
                        console.log("Connected to device: ", device.name)
                        // run some more async code once i'm connected to the device
                        try {
                            await bleManager.cancelDeviceConnection(device.id)
                        } catch {
                            console.log("Could not disconnect")
                        }
                        // await bleManager.connectToDevice(device.id)
                        //console.log("Connected to device")
                        //await bleManager.cancelDeviceConnection(device.id)
                        //console.log("Disconnected from device")
                    }
                }
            )
  

Комментарии:

1. если эта консоль. журнал никогда не происходит, bleManager.connectToDevice(device.id) никогда не разрешается (он может отклоняться, вы не обрабатываете там ошибки) — возможно, добавьте try / catch внутри обратного async (error, device) => { вызова

2. Вы совершенно правы, я добавил try catch для обоих, и теперь это работает! Большое вам спасибо!

Ответ №1:

@Jaromanda X предоставил решение:

Исправление состояло в том, чтобы добавить перехваты попыток вокруг асинхронных функций connectToDevice () и cancelDeviceConnection (), поскольку они отклонялись, и слушатель возвращался (следовательно, почему журнал «Подключен к устройству» никогда не печатался).

 bleManager.startDeviceScan(
                ['00001200-0000-1000-8000-00805f9b34fb'],
                { allowDuplicates: true },
                async (error, device) => {
                    // get services
                    let services = device.serviceUUIDs
                    // check if there are services being advertised
                    if (services amp;amp; services.includes('00001200-0000-1000-8000-00805f9b34fb')) {
                        console.log("Scanned a device with name: "   device.name   " | "   device.rssi)
                        console.log("Services:", services)
                        try {
                            await bleManager.connectToDevice(device.id)
                        } catch {
                            console.log("Could not connect")
                        }
                        console.log("Connected to device: ", device.name)
                        // run some more async code once i'm connected to the device
                        try {
                            await bleManager.cancelDeviceConnection(device.id)
                        } catch {
                            console.log("Could not disconnect")
                        }
                        // await bleManager.connectToDevice(device.id)
                        //console.log("Connected to device")
                        //await bleManager.cancelDeviceConnection(device.id)
                        //console.log("Disconnected from device")
                    }
                }
            )