Skip to content

Commit 2baf764

Browse files
committed
《select 表达式》
1 parent 427eea3 commit 2baf764

File tree

1 file changed

+52
-74
lines changed

1 file changed

+52
-74
lines changed

docs/select-expression.md

+52-74
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
22
/*
3+
34
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
45
*/
56
@@ -16,34 +17,28 @@ import org.junit.Test
1617
class SelectGuideTest {
1718
-->
1819

19-
20-
## Table of contents
21-
2220
<!--- TOC -->
2321

24-
* [Select expression (experimental)](#select-expression-experimental)
25-
* [Selecting from channels](#selecting-from-channels)
26-
* [Selecting on close](#selecting-on-close)
27-
* [Selecting to send](#selecting-to-send)
28-
* [Selecting deferred values](#selecting-deferred-values)
29-
* [Switch over a channel of deferred values](#switch-over-a-channel-of-deferred-values)
22+
* [select 表达式(试验性)](#select-expression-experimental)
23+
* [从通道查询](#selecting-from-channels)
24+
* [从关闭的通道查询](#selecting-on-close)
25+
* [查询并发送](#selecting-to-send)
26+
* [查询延迟值](#selecting-deferred-values)
27+
* [在延迟值通道上切换](#switch-over-a-channel-of-deferred-values)
3028

3129
<!--- END_TOC -->
3230

3331

3432

35-
## Select expression (experimental)
33+
## select 表达式(试验性)
3634

37-
Select expression makes it possible to await multiple suspending functions simultaneously and _select_
38-
the first one that becomes available.
35+
select 表达式可以同时等待多个挂起函数,并 _选择_ 第一个可用的。
3936

40-
> Select expressions are an experimental feature of `kotlinx.coroutines`. Their API is expected to
41-
evolve in the upcoming updates of the `kotlinx.coroutines` library with potentially
42-
breaking changes.
37+
> Select 表达式是 `kotlinx.coroutines` 的试验性功能。它们的 API 在 `kotlinx.coroutines` 库即将到来的更新中可能会有很大的变化。
4338
44-
### Selecting from channels
39+
### 从通道中查询
4540

46-
Let us have two producers of strings: `fizz` and `buzz`. The `fizz` produces "Fizz" string every 300 ms:
41+
我们现在有两个字符串生产者:`fizz` `buzz` 。其中 `fizz` 生产者每300毫秒产出 “Fizz” 字符串:
4742

4843
<div class="sample" markdown="1" theme="idea" data-highlight-only>
4944

@@ -56,9 +51,9 @@ fun CoroutineScope.fizz() = produce<String> {
5651
}
5752
```
5853

59-
</div>
6054

61-
And the `buzz` produces "Buzz!" string every 500 ms:
55+
56+
接着 `buzz` 每500毫秒产出 “Buzz!” 字符串:
6257

6358
<div class="sample" markdown="1" theme="idea" data-highlight-only>
6459

@@ -71,11 +66,9 @@ fun CoroutineScope.buzz() = produce<String> {
7166
}
7267
```
7368

74-
</div>
7569

76-
Using [receive][ReceiveChannel.receive] suspending function we can receive _either_ from one channel or the
77-
other. But [select] expression allows us to receive from _both_ simultaneously using its
78-
[onReceive][ReceiveChannel.onReceive] clauses:
70+
71+
使用 [receive][ReceiveChannel.receive] 挂起函数,我们可以从一个或另一个通道接收数据。但是 [select] 表达式允许我们使用其 [onReceive][ReceiveChannel.onReceive] 子句同时从两者接收:
7972

8073
<div class="sample" markdown="1" theme="idea" data-highlight-only>
8174

@@ -92,9 +85,9 @@ suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<St
9285
}
9386
```
9487

95-
</div>
9688

97-
Let us run it all seven times:
89+
90+
让我们运行7次:
9891

9992
<!--- CLEAR -->
10093

@@ -144,9 +137,9 @@ fun main() = runBlocking<Unit> {
144137

145138
</div>
146139

147-
> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-select-01.kt)
140+
> 你可以点击[这里](../core/kotlinx-coroutines-core/test/guide/example-select-01.kt)获得完整代码
148141
149-
The result of this code is:
142+
这段代码的结果如下:
150143

151144
```text
152145
fizz -> 'Fizz'
@@ -160,12 +153,9 @@ buzz -> 'Buzz!'
160153

161154
<!--- TEST -->
162155

163-
### Selecting on close
156+
### 从关闭的通道查询
164157

165-
The [onReceive][ReceiveChannel.onReceive] clause in `select` fails when the channel is closed causing the corresponding
166-
`select` to throw an exception. We can use [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] clause to perform a
167-
specific action when the channel is closed. The following example also shows that `select` is an expression that returns
168-
the result of its selected clause:
158+
select 中的 [onReceive][ReceiveChannel.onReceive] 子句在已经关闭的通道会失败,并导致相应的 `select` 抛出异常。我们可以使用 [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] 子句在关闭通道时执行特定操作。以下示例还显示了 `select` 是一个返回其查询方法结果的表达式:
169159

170160
<div class="sample" markdown="1" theme="idea" data-highlight-only>
171161

@@ -189,8 +179,7 @@ suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): St
189179

190180
</div>
191181

192-
Let's use it with channel `a` that produces "Hello" string four times and
193-
channel `b` that produces "World" four times:
182+
现在有一个产出四次 “Hello” 字符串的 `a` 通道、一个产出四次 “World” 字符串的 `b` 通道,我们在这两个通道上使用它:
194183

195184
<!--- CLEAR -->
196185

@@ -235,9 +224,9 @@ fun main() = runBlocking<Unit> {
235224

236225
</div>
237226

238-
> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-select-02.kt)
227+
> 你可以点击[这里](../core/kotlinx-coroutines-core/test/guide/example-select-02.kt)获得完整代码
239228
240-
The result of this code is quite interesting, so we'll analyze it in mode detail:
229+
这段代码的结果非常有趣,所以我们将在模式细节中分析它:
241230

242231
```text
243232
a -> 'Hello 0'
@@ -252,23 +241,19 @@ Channel 'a' is closed
252241

253242
<!--- TEST -->
254243

255-
There are couple of observations to make out of it.
244+
有几个结果可以通过观察得出。
245+
246+
首先,`select` 偏向于第一个子句,当可以同时选到多个子句时,第一个子句将被选中。在这里,两个通道都在不断地生成字符串,因此作为 select 中的第一个子句的通道获胜。然而因为我们使用的是无缓冲通道,所以 `a` 在其发送调用时会不时被挂起,进而 `b` 也有机会发送。
256247

257-
First of all, `select` is _biased_ to the first clause. When several clauses are selectable at the same time,
258-
the first one among them gets selected. Here, both channels are constantly producing strings, so `a` channel,
259-
being the first clause in select, wins. However, because we are using unbuffered channel, the `a` gets suspended from
260-
time to time on its [send][SendChannel.send] invocation and gives a chance for `b` to send, too.
248+
第二个观察结果是,当通道已经关闭时,会立即选择 [onReceiveOrNull][ReceiveChannel.onReceiveOrNull]
261249

262-
The second observation, is that [onReceiveOrNull][ReceiveChannel.onReceiveOrNull] gets immediately selected when the
263-
channel is already closed.
264250

265-
### Selecting to send
266251

267-
Select expression has [onSend][SendChannel.onSend] clause that can be used for a great good in combination
268-
with a biased nature of selection.
252+
### 查询并发送
269253

270-
Let us write an example of producer of integers that sends its values to a `side` channel when
271-
the consumers on its primary channel cannot keep up with it:
254+
Select 表达式具有 [onSend][SendChannel.onSend] 子句,可以很好的与选择的偏向特性结合使用。
255+
256+
我们来编写一个整数生成器的示例,当主通道上的消费者无法跟上它时,它会将值发送到 `side` 通道上:
272257

273258
<div class="sample" markdown="1" theme="idea" data-highlight-only>
274259

@@ -286,7 +271,7 @@ fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
286271

287272
</div>
288273

289-
Consumer is going to be quite slow, taking 250 ms to process each number:
274+
消费者将会非常缓慢,每个数值处理需要250毫秒:
290275

291276
<!--- CLEAR -->
292277

@@ -324,11 +309,11 @@ fun main() = runBlocking<Unit> {
324309
```
325310

326311
</div>
327-
328-
> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-select-03.kt)
329-
330-
So let us see what happens:
331-
312+
313+
> 你可以点击[这里](../core/kotlinx-coroutines-core/test/guide/example-select-03.kt)获得完整代码
314+
315+
让我们看看会发生什么:
316+
332317
```text
333318
Consuming 1
334319
Side channel has 2
@@ -345,11 +330,9 @@ Done consuming
345330

346331
<!--- TEST -->
347332

348-
### Selecting deferred values
333+
### 查询延迟值
349334

350-
Deferred values can be selected using [onAwait][Deferred.onAwait] clause.
351-
Let us start with an async function that returns a deferred string value after
352-
a random delay:
335+
延迟值可以使用 [onAwait][Deferred.onAwait] 子句查询。让我们启动一个延迟随机时间后返回延迟字符串的异步方法:
353336

354337
<div class="sample" markdown="1" theme="idea" data-highlight-only>
355338

@@ -362,7 +345,7 @@ fun CoroutineScope.asyncString(time: Int) = async {
362345

363346
</div>
364347

365-
Let us start a dozen of them with a random delay.
348+
让我们启动十几个,每个都延迟随机的时间。
366349

367350
<div class="sample" markdown="1" theme="idea" data-highlight-only>
368351

@@ -375,10 +358,7 @@ fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
375358

376359
</div>
377360

378-
Now the main function awaits for the first of them to complete and counts the number of deferred values
379-
that are still active. Note, that we've used here the fact that `select` expression is a Kotlin DSL,
380-
so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
381-
of deferred values to provide `onAwait` clause for each deferred value.
361+
现在主函数等待第一个函数完成,并统计仍处于激活状态的延迟值的数量。注意,我们在这里的使用,事实上是把 `select` 表达式作为一种Kotlin DSL,所以我们可以用任意代码为它提供子句。在这种情况下,我们遍历一个延迟值的队列,为每个延迟值提供 `onAwait` 子句。
382362

383363
<!--- CLEAR -->
384364

@@ -418,9 +398,9 @@ fun main() = runBlocking<Unit> {
418398

419399
</div>
420400

421-
> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-select-04.kt)
401+
> 你可以点击[这里](../core/kotlinx-coroutines-core/test/guide/example-select-04.kt)获得完整代码
422402
423-
The output is:
403+
输出如下:
424404

425405
```text
426406
Deferred 4 produced answer 'Waited for 128 ms'
@@ -429,11 +409,9 @@ Deferred 4 produced answer 'Waited for 128 ms'
429409

430410
<!--- TEST -->
431411

432-
### Switch over a channel of deferred values
412+
### 在延迟值通道上切换
433413

434-
Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
435-
deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
436-
[onReceiveOrNull][ReceiveChannel.onReceiveOrNull] and [onAwait][Deferred.onAwait] clauses in the same `select`:
414+
我们现在来编写一个通道生产者函数,它消费一个产生延迟字符串的通道,并等待每个接收的延迟值,但只在下一个延迟值到达或者通道关闭之前。此示例将 [onReceiveOrNull][ReceiveChannel.onReceiveOrNull][onAwait][Deferred.onAwait] 子句放在同一个 `select` 中:
437415

438416
<div class="sample" markdown="1" theme="idea" data-highlight-only>
439417

@@ -462,7 +440,7 @@ fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) =
462440

463441
</div>
464442

465-
To test it, we'll use a simple async function that resolves to a specified string after a specified time:
443+
为了测试它,我们将用一个简单的异步函数,它在特定的延迟后返回特定的字符串:
466444

467445

468446
<div class="sample" markdown="1" theme="idea" data-highlight-only>
@@ -476,8 +454,7 @@ fun CoroutineScope.asyncString(str: String, time: Long) = async {
476454

477455
</div>
478456

479-
The main function just launches a coroutine to print results of `switchMapDeferreds` and sends some test
480-
data to it:
457+
主函数只是启动一个协程来打印 `switchMapDeferreds` 的结果并向它发送一些测试数据:
481458

482459
<!--- CLEAR -->
483460

@@ -537,9 +514,9 @@ fun main() = runBlocking<Unit> {
537514

538515
</div>
539516

540-
> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-select-05.kt)
517+
> 你可以点击[这里](../core/kotlinx-coroutines-core/test/guide/example-select-05.kt)获得完整代码
541518
542-
The result of this code:
519+
这段代码的结果:
543520

544521
```text
545522
BEGIN
@@ -552,6 +529,7 @@ Channel was closed
552529

553530
<!--- MODULE kotlinx-coroutines-core -->
554531
<!--- INDEX kotlinx.coroutines -->
532+
555533
[Deferred.onAwait]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/on-await.html
556534
<!--- INDEX kotlinx.coroutines.channels -->
557535
[ReceiveChannel.receive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html

0 commit comments

Comments
 (0)