[英]multiple async-await in kotlin
promoType = [list of string]中的obj更像是在這里運行的10個firebase查詢,查看10個特定的節點集並進一步向下。
我不確定,我是否需要對每個查詢進行異步/等待,但我想要的只有10個這樣的查詢才能運行,然后讓我知道couponKey是否為空。 我想要做的就是顯示輸入的優惠券是否正確。
此外,在changeUserType(couponKey,couponFoundAtKey)中,發生了一些數據庫寫操作。
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
}
}
我發現你的代碼有幾個問題:
async(UI)
沒有意義 async(CommonPool)
也沒有意義,因為您的數據庫調用已經是異步的 async
后立即await
它,使它不是真正的“異步”(但參見上文,整個過程是異步的,有或沒有這個) 您的代碼應該更簡單。 你應該聲明一個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()
}
}
})
}
要調用此功能,請在呼叫站點使用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()
}
}
你說changeUserType
執行一些數據庫操作,所以我將它們包裝在withContext(CommonPool)
。
另請注意,我在函數外部的promo類型中提取了循環。 這將導致查詢按順序執行,但您可以編寫不同的調用代碼來實現並行查找:
var numDone = 0
var found = false
promoType.forEach { type ->
launch(UI) {
fetchPromo(type, "promo-code-et")
.also { numDone++ }
?.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()
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.