通过标签 Kotlin 从内部嵌套协程返回

问题描述 投票:0回答:2

用例:我有很多操作想要从主线程异步发生,但又彼此并行。

val scope = CoroutineScope(Dispatchers.IO)
val items = // List of items to do something.

scope.launch {
    items.forEach { item ->
        scope.launch {
            if (itemFailsValidation(item)) {
                // Here I want to skip this item but continue the forEach loop.
                return@launch // "There is more than one label with such a name in this" scope"
            }
            doSomethingThatMightTakeABit(item)
         }
     }
}

如果我尝试添加一个标签,例如

[email protected]
,编辑器会说“标签是多余的,因为它不能在 ''break''、''Continue'' 或 ''return'' 表达式中引用”

有人知道这样做的好方法吗?

kotlin asynchronous kotlin-coroutines coroutine coroutinescope
2个回答
5
投票

如果我们需要从 lambda 表达式返回,我们必须对其进行 标记并限定 return。为了让您的案例从内部协程返回:

scope.launch {
    items.forEach { item ->
        scope.launch innerScope@ {
            if (itemFailsValidation(item)) {
                return@innerScope
            }
            doSomethingThatMightTakeABit(item)
        }
    }
}

但是我们可以简化您的情况并重写代码而不使用标签:

scope.launch {
    items.forEach { item ->
        if (!itemFailsValidation(item)) {
            scope.launch { doSomethingThatMightTakeABit(item) }
        }
    }
}

// OR

items.forEach { item ->
    if (!itemFailsValidation(item)) {
        scope.launch { doSomethingThatMightTakeABit(item) }
    }
}    

如果你想等待所有协程完成并在 UI 线程上执行某些操作:

scope.launch(Dispatchers.Main) {
    processItemsInBackground()

    // update UI after processing is finished
}

suspend fun processItemsInBackground() = withContext(Dispatchers.IO) {
    // withContext waits for all children coroutines
    items.forEach { item ->
        if (!itemFailsValidation(item)) {
            launch { doSomethingThatMightTakeABit(item) }
        }
    }
}

2
投票

您可以使用

name@
关键字更改 lambda 的名称。

示例:

scope.launch outerCoroutine@ {
    items.forEach { item ->
        scope.launch {
            if (itemFailsValidation(item)) {
                return@outerCoroutine
            }
            doSomethingThatMightTakeABit(item)
         }
     }
}

此功能没有正确记录,但是像This statements这样的一些文档中有演示用法,并且标准库中定义的一些函数使用了它。

编辑:这实际上记录在返回和跳转

© www.soinside.com 2019 - 2024. All rights reserved.