Как мне написать последовательность обещаний в Котлине? - PullRequest
0 голосов
/ 07 ноября 2018

Можно ли написать последовательность обещание (или задач), используя только Kotlin?

Например, последовательность обещаний в JavaScript записывается как:

const SLEEP_INTERVAL_IN_MILLISECONDS = 200;

const alpha = function alpha (number) {
    return new Promise(function (resolve, reject) {
        const fulfill = function() {
            return resolve(number + 1);
        };

        return setTimeout(fulfill, SLEEP_INTERVAL_IN_MILLISECONDS);
    });
};

const bravo = function bravo (number) {
    return new Promise(function (resolve, reject) {
        const fulfill = function() {
            return resolve(Math.ceil(1000*Math.random()) + number);
        };
        return setTimeout(fulfill, SLEEP_INTERVAL_IN_MILLISECONDS);
    });
};

const charlie = function charlie (number) {
    return new Promise(function (resolve, reject) {
        return (number%2 == 0) ? reject(number) : resolve(number);
    });
};

function run() {
    return Promise.resolve(42)
        .then(alpha)
        .then(bravo)
        .then(charlie)
        .then((number) => {
            console.log('success: ' + number)
        })
        .catch((error) => {
            console.log('error: ' + error);
        });
}

run();

Каждая функция также возвращает Обещание с результатом асинхронной обработки, которое будет разрешено / отклонено с помощью следующего следующего обещания.

Я знаю, как написать это, используя RxKotlin , но я пытаюсь выяснить, как написать это, используя библиотеку сопрограмм или любую другую стандартную функцию.

1 Ответ

0 голосов
/ 07 ноября 2018

Как вы упомянули, сопрограммы являются стандартной функцией.

Вы должны использовать ключевое слово suspend, если функция будет приостановлена, например, IO или если вы вызываете другую функцию suspend, например, delay.

Обработка ошибок может быть выполнена с помощью обычной инструкции try-catch.

import kotlinx.coroutines.delay
import java.lang.Exception
import kotlin.math.ceil

const val SLEEP_INTERVAL_IN_MILLISECONDS = 200

suspend fun alpha(number: Int): Int {
    delay(SLEEP_INTERVAL_IN_MILLISECONDS)
    return number + 1
}

suspend fun bravo(number: Int): Int {
    delay(SLEEP_INTERVAL_IN_MILLISECONDS)
    return ceil(1000 * Math.random() + number).toInt()
}

fun charlie(number: Int): Int =
    number.takeIf { it % 2 == 0 } ?: throw IllegalStateException(number.toString())

suspend fun run() {
    try {
        val result = charlie(bravo(alpha(42)))
        println(result)
    } catch (e: Exception) {
        println(e)
    }
}

suspend fun main() {
    run()
}

Если вам нравится более функциональный стиль для обработки ошибок, вы можете пойти с этим:

suspend fun run() {
    runCatching { charlie(bravo(alpha(42))) }
        .onFailure { println(it) }
        .onSuccess { println(it) }
}
...