multiple async-await in kotlin

Multi tool use
Multi tool use
The name of the picture


multiple async-await in kotlin



obj in promoType = [list of string]
its more like 10 firebase queries are running here, looking in 10 particular set of nodes and going down further.



what i'm not sure, whether i require to put on async / await on each of the queries, but all i want is 10 of these queries to run and then result me in whether a couponKey is empty or not. All i want to do is to display whether a coupon entered was correct or not.



further, in changeUserType(couponKey, couponFoundAtKey), some database write operations occur.


fun checkPromo(promoCodeET: String) = async(UI) {
try {
val database = PersistentFirebaseUtil.getDatabase().reference
val job = async(CommonPool) {

for (obj in promoType) {
val query = database.child("promos").child(obj).orderByChild("promoCode").equalTo(promoCodeET)

query.addListenerForSingleValueEvent(object :
ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
if (dataSnapshot.exists()) {
couponKey = dataSnapshot.key.toString()
couponFoundAtKey = dataSnapshot.children.first().key.toString()
if (couponKey.isNotEmpty())
changeUserType(couponKey, couponFoundAtKey)
flag = true
}
}

override fun onCancelled(error: DatabaseError) {
// Failed to read value
}
})
if (flag) break
}
}
job.await()

}
catch (e: Exception) {
}
finally {
if (couponKey.isEmpty()){
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
flag = true
}
}




1 Answer
1



There are several things I find wrong with your code:


async(UI)


async(CommonPool)


await


async



Your code should be much simpler. You should declare a suspend fun whose return value is the pair (couponKey, coupon):


suspend fun


(couponKey, coupon)


suspend fun fetchPromo(promoType: String, promoCodeET: String): Pair<String, String>? =
suspendCancellableCoroutine { cont ->
val database = PersistentFirebaseUtil.getDatabase().reference
val query = database.child("promos").child(promoType)
.orderByChild("promoCode").equalTo(promoCodeET)
query.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
cont.resume(
dataSnapshot
.takeIf { it.exists() }
?.let { snapshot ->
snapshot.key.toString()
.takeIf { it.isNotEmpty() }
?.let { key ->
Pair(key, snapshot.children.first().key.toString())
}
}
)
}

override fun onCancelled(error: DatabaseError?) {
if (error != null) {
cont.resumeWithException(MyException(error))
} else {
cont.cancel()
}
}
})
}



To call this function, use a launch(UI) at the call site. Change the user type once you get a non-null value:


launch(UI)


launch(UI) {
var found = false
for (type in promoType) {
val (couponKey, coupon) = fetchPromo(type, "promo-code-et") ?: continue
found = true
withContext(CommonPool) {
changeUserType(couponKey, coupon)
}
break
}
if (!found) {
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
}



You say that changeUserType performs some database operations, so I wrapped them in a withContext(CommonPool).


changeUserType


withContext(CommonPool)



Note also that I extracted the loop over promo types outside the function. This will result in queries being performed sequentially, but you can just write different calling code to achieve parallel lookup:


var numDone = 0
var found = false
promoType.forEach { type ->
launch(UI) {
fetchPromo(type, "promo-code-et")
.also { numDone++ }
.takeIf { it != null }
?.also { (couponKey, coupon) ->
found = true
launch(CommonPool) {
changeUserType(couponKey, coupon)
}
}
?: if (numDone == promoType.size && !found) {
Toast.makeText(this@Coupon, "Invalid coupon", Toast.LENGTH_LONG).show()
}
}
}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

iQoJS nIIH8R,ac z Gn,4X4muUX7hZEL
slAsHgs,uoJzJDPDeQ zCWlwDK2 MM5B,TH,l1lrddoKo1 RcCX8FQJWt9xNO50w 01Mcc2

Popular posts from this blog

Keycloak server returning user_not_found error when user is already imported with LDAP

PHP parse/syntax errors; and how to solve them?

415 Unsupported Media Type while sending json file over REST Template