Rename subscribingGet to syncFromEvent, subscribingGetAsync to asyncFromEvent; Improve docs

This commit is contained in:
Him188 2020-04-21 14:30:35 +08:00
parent 5234226788
commit d94b1d3279

View File

@ -7,47 +7,53 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("unused")
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.SinceMirai import net.mamoe.mirai.utils.SinceMirai
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.suspendCoroutine
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KClass
/** /**
* 挂起当前协程, 监听这个事件, 并尝试从这个事件中获取一个值. * 挂起当前协程, 监听事件 [E], 并尝试从这个事件中**同步**一个值, 在超时时抛出 [TimeoutCancellationException]
* *
* [mapper] 抛出了一个异常, 本函数会立即抛出这个异常. * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制.
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
* *
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制 * @see asyncFromEvent 本函数的异步版本
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [subscribingGet] 会返回这个值
* *
* @see subscribingGetAsync 本函数的异步版本 * @throws TimeoutCancellationException 在超时后抛出.
* @throws Throwable [mapper] 抛出任何异常时, 本函数会抛出该异常
*/ */
@SinceMirai("0.29.0") @JvmSynthetic
@MiraiExperimentalAPI @SinceMirai("0.38.0")
suspend inline fun <reified E : Event, R : Any> subscribingGet( suspend inline fun <reified E : Event, R : Any> syncFromEvent(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常 noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): R { ): R {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" } require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
return subscribingGetOrNull(timeoutMillis, mapper) ?: error("timeout subscribingGet") return syncFromEventOrNull(timeoutMillis, mapper) ?: error("timeout $timeoutMillis ms asyncFromEvent")
} }
/** /**
* 挂起当前协程, 监听这个事件, 并尝试从这个事件中获取一个值. * 挂起当前协程, 监听这个事件, 并尝试从这个事件中获取一个值, 在超时时返回 `null`
*
* [mapper] 抛出了一个异常, 本函数会立即抛出这个异常.
* *
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制 * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [subscribingGet] 会返回这个值 * @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值.
* *
* @see subscribingGetAsync 本函数的异步版本 * @return 超时返回 `null`, 否则返回 [mapper] 返回的第一个非 `null` .
*
* @see asyncFromEvent 本函数的异步版本
* @throws Throwable [mapper] 抛出任何异常时, 本函数会抛出该异常
*/ */
@SinceMirai("0.29.0") @JvmSynthetic
@MiraiExperimentalAPI @SinceMirai("0.38.0")
suspend inline fun <reified E : Event, R : Any> subscribingGetOrNull( suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常 noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): R? { ): R? {
@ -55,11 +61,11 @@ suspend inline fun <reified E : Event, R : Any> subscribingGetOrNull(
return if (timeoutMillis == -1L) { return if (timeoutMillis == -1L) {
coroutineScope { coroutineScope {
subscribingGetOrNullImpl<E, R>(this, mapper) syncFromEventOrNullImpl<E, R>(E::class, this, mapper)
} }
} else { } else {
withTimeoutOrNull(timeoutMillis) { withTimeoutOrNull(timeoutMillis) {
subscribingGetOrNullImpl<E, R>(this, mapper) syncFromEventOrNullImpl<E, R>(E::class, this, mapper)
} }
} }
} }
@ -71,16 +77,42 @@ suspend inline fun <reified E : Event, R : Any> subscribingGetOrNull(
* *
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制 * @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
* @param coroutineContext 额外的 [CoroutineContext] * @param coroutineContext 额外的 [CoroutineContext]
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [subscribingGet] 会返回这个值 * @param mapper 过滤转换器. 返回非 `null` 则代表得到了需要的值. [syncFromEvent] 会返回这个值
*/ */
@SinceMirai("0.29.0") @Suppress("DeferredIsResult")
@MiraiExperimentalAPI @SinceMirai("0.38.0")
inline fun <reified E : Event, R : Any> CoroutineScope.subscribingGetAsync( inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常 noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): Deferred<R> = this.async(coroutineContext) { ): Deferred<R?> {
subscribingGet(timeoutMillis, mapper) require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
return this.async(coroutineContext) {
syncFromEventOrNull(timeoutMillis, mapper)
}
}
/**
* 异步监听这个事件, 并尝试从这个事件中获取一个值.
*
* [mapper] 抛出的异常将会被传递给 [Deferred.await] 抛出.
*
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
* @param coroutineContext 额外的 [CoroutineContext]
* @param mapper 过滤转换器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
*/
@Suppress("DeferredIsResult")
@SinceMirai("0.38.0")
inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEvent(
timeoutMillis: Long = -1,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
noinline mapper: suspend E.(E) -> R? // 不要 crossinline: crossinline 后 stacktrace 会不正常
): Deferred<R> {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
return this.async(coroutineContext) {
syncFromEvent(timeoutMillis, mapper)
}
} }
@ -88,24 +120,19 @@ inline fun <reified E : Event, R : Any> CoroutineScope.subscribingGetAsync(
//// internal //// internal
////////////// //////////////
@PublishedApi @PublishedApi
internal suspend inline fun <reified E : Event, R> subscribingGetOrNullImpl( internal suspend fun <E : Event, R> syncFromEventOrNullImpl(
eventClass: KClass<E>,
coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
noinline mapper: suspend E.(E) -> R? mapper: suspend E.(E) -> R?
): R? { ): R? = suspendCoroutine { cont ->
var result: Result<R?> = Result.success(null) // stub
var listener: Listener<E>? = null var listener: Listener<E>? = null
@Suppress("DuplicatedCode") // for better performance @Suppress("DuplicatedCode") // for better performance
listener = coroutineScope.subscribe { listener = coroutineScope.subscribe(eventClass) {
result = kotlin.runCatching { cont.resumeWith(kotlin.runCatching {
mapper.invoke(this, it) ?: return@subscribe ListeningStatus.LISTENING mapper.invoke(this, it) ?: return@subscribe ListeningStatus.LISTENING
} })
listener!!.complete() listener!!.complete()
return@subscribe ListeningStatus.STOPPED return@subscribe ListeningStatus.STOPPED
} }
listener.join()
return result.getOrThrow()
} }