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

Цепочки и комбинирование

Промисы становятся ещё мощнее, когда их объединяют. Чаще всего нужно дождаться нескольких сразу. await принимает список промисов и возвращает их результаты по порядку:

my @jobs = (start { 1 }), (start { 2 }), (start { 3 });
say await @jobs;     # (1 2 3)
say [+] await @jobs; # 6

Три задания выполняются одновременно; await @jobs дожидается их всех и отдаёт (1, 2, 3). Поскольку результаты возвращаются в том же порядке, что и промисы, их можно свернуть как обычно.

Работу можно и надстроить над промисом методом .then, который выполняет последующий блок, когда промис завершится. Внутри него .result — это значение исходного промиса:

my $p = start { 10 };
my $q = $p.then({ .result * 2 });
say await $q; # 20

$q — новый промис, удваивающий результат $p. Ожидание его даёт 20.

У блока нет явного параметра, поэтому он получает завершившийся промис в переменной темы $_ — вот почему работает голое .result: на самом деле это $_.result. Если вам хочется дать этому промису имя, возьмите стрелочный блок:

my $q = $p.then(-> $prev { $prev.result * 2 });

Ведёт себя это в точности так же: $prev — исходный промис $p, а $prev.result — его значение.

С помощью start, await и .then можно описывать целые конвейеры конкурентной работы: запускать множество задач, объединять их результаты и строить новые задачи из старых — и всё это не прикасаясь к потокам напрямую.

Практика

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

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

Тест — Промисы   |   Тест — Комбинирование промисов


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