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

Обещания (Vow) 🆕

Когда вы сами вызываете $p.keep(...), уладить промис может любой, кто держит $p. Иногда нужно обратное: улаживать промис должен только тот код, который производит результат, а всем остальным позволено лишь дожидаться. Это разделение и есть обещание (vow).

Promise.new даёт вам промис; вызов .vow у него возвращает Vow — единоличное право исполнить или сломать этот промис. С этого момента промис предполагается доступным только для чтения: улаживают его через обещание. Обычная форма — производитель, который держит обещание при себе и возвращает только промис:

sub after($seconds) {
    my $p = Promise.new;
    my $v = $p.vow;                       # забираем право улаживать
    start {
        sleep $seconds;
        $v.keep("done after $seconds s"); # улаживаем через обещание
    }
    return $p;                            # вызывающим достаётся только сторона для чтения
}

my $job = after(0.2);
say $job.status;   # Planned
say await $job;    # done after 0.2 s

Взятие обещания делает промис по-настоящему доступным только для чтения: с этого момента $p.keep и $p.break отвергаются, потому что единоличное право улаживать теперь принадлежит обещанию.

my $p = Promise.new;
my $v = $p.vow;

$p.keep(1); # умирает: Access denied to keep/break this Promise; already vowed

Итак, вызывающая сторона может дождаться промиса через await, надстроить над ним .then или проверить его .status, но уладить его не может — на это способен лишь держатель обещания. Именно так библиотеки превращают API на обратных вызовах и событиях в обычные промисы: создают промис, держат его обещание и исполняют его изнутри обратного вызова, когда событие наконец наступает.

Ровно это start и делает за вас за кулисами: он создаёт промис, оставляет обещание себе и улаживает промис значением блока (или ломает его, если блок умер). Создание промиса и его обещания вручную просто позволяет сделать то же самое, когда результат приходит не из одного блока кода.

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

Статус промиса 🆕   |   Соедините промисы в цепочку


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