Home > Software engineering >  Not able to achieve concurrency with swift in React native app
Not able to achieve concurrency with swift in React native app

Time:08-25

Im trying to achieve encryption tasks running parallelly in native.

My implementation is as below:

It is each time JS call native, the task will be wrapped into queue.async:-

let queue = DispatchQueue(label: "decrypting")

@objc(decrypt:withKey:iv:tag:withResolver:withRejecter:)

func decrypt(hexCipherText: String, key: String, iv: String, tag: String, resolve:@escaping RCTPromiseResolveBlock, reject:@escaping RCTPromiseRejectBlock) -> Void {
    queue.async {
        do {
            guard let keyData = Data(hexString: key) else {
                throw CryptoError.runtimeError("Invalid key")
            }

            let decryptedData = try self.decryptData(cipherData: hexCipherText.hexaData, key: keyData, iv: iv, tag: tag)
            resolve(decryptedData.hexadecimal)
        } catch CryptoError.runtimeError(let errorMessage) {
            reject("InvalidArgumentError", errorMessage, nil)
        } catch {
            reject("DecryptionError", "Failed to decrypt", error)
        }
    }
}

However when running at the same time of multiple JS calls to native encryption, it does not work as expected, my performance is still slow like before.

for (const data of encryptedArr) {
   await JSCallNativeEncryption(data);
}

or without await:

for (const data of encryptedArr) {
   JSCallNativeEncryption(data)
      .then(a => console.log(a))
      .catch(e => console.log(e))
}

CodePudding user response:

By default a DispatchQueue is serial.

See documentation here: https://developer.apple.com/documentation/dispatch/dispatchqueue/2300059-init

The attributes to associate with the queue. Include the concurrent attribute to create a dispatch queue that executes tasks concurrently. If you omit that attribute, the dispatch queue executes tasks serially.

Instantiate your queue with the .concurrent attribute:

let queue = DispatchQueue(label: "decrypting", attributes: .concurrent)

You also need to update your loop.

await will wait for a result before continuing, effectively making your calls serial.

If using promise syntax, you need to keep a reference to the JSCallNativeEncryption call, otherwise the object will get deallocated on the next iteration of the loop.

So something like this:

const unresolvedPromises = encryptedArr.map(data => JSCallNativeEncryption(data));
const results = await Promise.all(unresolvedPromises);
  • Related