Можно ли прекратить блок кода обещания из другого обещания? - PullRequest
0 голосов
/ 23 октября 2018

Я написал эту тестовую программу:

await Promise.anyof(
  Promise.allof((^5).map: {start { sleep 10; say "done $_" } }),
  Promise.in(5).then: { say 'ouch' }
);
sleep 10;

Когда второе обещание истекает, оно выводит «ой», и ожидание завершается, но блок кода первого обещания все еще выполняется.Еще через пять секунд его пять процессов завершаются и выдают «done»:

$ ./test1.p6
ouch
done 0
done 1
done 2
done 3
done 4

Я попытался завершить первое обещание, присвоив его переменной, а затем вызвав метод .break из второго обещания, но этоне работает.

Есть ли способ убить первое обещание и остальные пять подчиненных обещаний, которые он начал?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Попробуйте с всякий раз, когда :

$ perl6 -e '

react {
   for ^5 -> $num {
      whenever start { sleep 10 } {
         say "done $num"
      }
   }
   whenever Promise.in: 5 {
      say "ouch";
      done
   }
}

' ouch
0 голосов
/ 23 октября 2018

Вы должны как-то сказать процессу, что он не должен завершаться.

my $cancel = Cancellation.new;

await Promise.anyof(
  Promise.allof(
    (^5).map: {
      last if $cancel.cancelled;

      start {
        sleep 10;
        say "done $_" unless $cancel.cancelled
      }
    }
  ),
  Promise.in(5).then: {
    $cancel.cancel;
    say 'ouch'
  }
);

Если вы хотите что-то вроде Promise.in(), которое можно отменить, давайте начнем с глядя на существующий код .

method in(Promise:U: $seconds, :$scheduler = $*SCHEDULER) {
    my $p   := self.new(:$scheduler);
    my $vow := $p.vow;
    $scheduler.cue({ $vow.keep(True) }, :in($seconds));
    $p
}

Обратите внимание, что результатом $scheduler.cue является аннулирование.

Я просто собираюсь обернуть обещание и аннулирование вкласс для простоты.
(я не хочу переопределять каждый метод).

class Cancellable-Timer {
    has Promise      $.Promise;
    has              $!vow;
    has Cancellation $!cancel;

    method !SET-SELF ( $!promise, $!vow, $!cancel ){
        self
    }

    method in (::?CLASS:U: $seconds, :$scheduler = $*SCHEDULER) {
        my $p   := Promise.new(:$scheduler);
        my $vow := $p.vow;
        my $cancel = $scheduler.cue({ $vow.keep(True) }, :in($seconds));
        self.bless!SET-SELF($p,$vow,$cancel);
    }

    method cancel ( --> Nil ) {
        # potential concurrency problem
        if $!Promise.status == Planned {
            $!cancel.cancel;          # cancel the timer
            $!vow.break("cancelled"); # break the Promise
        }
    }

    method cancelled () {
        # Ignore any concurrency problems by using the Promise
        # as the sole source of truth.
        $!Promise.status ~~ PromiseStatus::Broken
    }
}

my $timer = Cancellable-Timer.in(1);
my $say = $timer.Promise.then: *.say;
Promise.in(0.1).then: {$timer.cancel};
await $say;

Обратите внимание, что вышеприведенный класс является просто черновым первым черновиком.

...