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);