Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Реактивное программирование / await

Ожидание промиса

await принимает промис, дожидается его завершения и возвращает его результат:

my $p = start { 7 * 6 };
say await $p; # 42

Программа приостанавливается на await ровно настолько, насколько нужно, а затем продолжает работу со значением, которое произвёл промис.

Получив несколько промисов, await дожидается всех и возвращает их результаты в том же порядке, в каком промисы стоят в списке:

my @jobs = (start { 5 }), (start { 10 }), (start { 15 });
say await @jobs;     # (5 10 15)
say [+] await @jobs; # 30

Задачи выполняются конкурентно, но await @jobs не вернёт управление, пока не завершится каждая из них. Каждый результат затем оказывается на той же позиции, что и его промис в @jobs, — независимо от того, какая задача закончилась первой.

Если ожидаемый промис оказался сломан — его блок бросил исключение, — await перебрасывает это исключение в точке await. Значит, ошибки фоновой работы всплывают там, где вы её дожидаетесь, и обрабатывать их можно привычными try / CATCH из части об исключениях:

my $p = start { die 'no such file' };

my $result = try await $p;
say $result // "the job failed: $!";

Программа печатает:

the job failed: no such file

die происходит в фоновом потоке, но исключение путешествует вместе с промисом и выныривает на await. Там его перехватывает try, оставляя $result неопределённым, а ошибку — в $!; так что сбой в конкурентной работе обрабатывается точно так же, как любое другое исключение. Поэтому ожидание — не только про получение значения: это ещё и момент, когда конкурентная работа воссоединяется с основным потоком выполнения, как с результатами, так и с ошибками.

Практика

Пройдите 2 теста по содержанию этой темы.

Навигация по курсу

await   |   Тест — await


💪 Или перейдите сразу к упражнениям этого раздела.