【问题标题】:Why am I not allowed to break a Promise?为什么我不允许违反 Promise?
【发布时间】:2020-10-05 16:43:00
【问题描述】:

以下简单的 Promise 是发誓的,我不能破坏它。

my $my_promise = start {
    loop {}   # or sleep x;
    
    'promise response'
}

say 'status : ', $my_promise.status;      # status : Planned

$my_promise.break('promise broke');       # Access denied to keep/break this Promise; already vowed
                                          # in block <unit> at xxx line xxx

这是为什么呢?

【问题讨论】:

  • 从语义上讲,如果它是可以被破坏的东西,它就不是一个很好的名字。

标签: promise raku rakudo


【解决方案1】:

因为承诺誓言,你无法改变它:只有真正拥有誓言的东西,才能打破承诺。这就是 vow 功能的意图。

你想通过违背承诺来实现什么?是否停止在start 块内完成的工作?打破承诺不会那样做。并且明确添加了vow 机制,以防止您认为它会以某种方式停止start 块内的工作。

如果您希望 start 块内的工作可中断,则需要添加某种定期检查的信号量,例如:

my int $running = 1;
my $my_promise = start {
    while $running {
        # do stuff
    }
    $running
}

# do other stuff
$running = 0;
await $my_promise;

希望这是有道理的。

【讨论】:

    【解决方案2】:

    在 Jonathans 的评论中,here 解释了您不能直接从外部保持/破坏 Promise 或在线程池上停止 Promise 的原因。

    Promises 的常见误用来自超时模式。

    await Promise.anyof(
        start { sleep 4; say "finished"; },
        Promise.in( 1 )
    );
    say "moving on...";
    sleep;
    

    打印“完成”。当用户意识到他的下一个合乎逻辑的步骤是尝试杀死过时的 Promise。虽然解决它的唯一正确方法是让 Promise 意识到不再需要它的工作。例如通过定期检查一些共享变量。

    如果 Promise 上的阻塞代码(例如数据库查询)运行时间过长,并且您想从主线程终止它,事情就会变得复杂。这在 Promises 上是不可行的。您所能做的就是确保 Promise 将在有限时间内运行(例如在 MySQL 上通过在运行查询之前设置 MAX_EXECUTION_TIME)。然后你有选择:

    • 你可以磨牙,耐心等待Promise完成。例如,如果您确实必须在主线程中断开数据库。
    • 或者您可以立即继续并允许“废弃”的 Promise 自行完成,而不会收到结果。在这种情况下,您应该通过使用 Semaphore 或在专用 ThreadPoolScheduler 上运行它们来控制这些 Promise 中有多少可以在后台堆叠。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-03
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 2013-04-11
      • 2014-03-01
      • 2017-09-02
      • 1970-01-01
      相关资源
      最近更新 更多