【问题标题】:User input with timeout doesn't work as hoped超时的用户输入无法按预期工作
【发布时间】:2020-04-29 06:32:31
【问题描述】:

为什么在超时后循环不能像以前一样工作(不再打印用户输入)?

#!/usr/bin/env raku

loop {
    my $str;
    my $timeout = Promise.in( 5 ).then({
        $str = 'Timeout';
    });
    my $user = Promise.start({
        $str = prompt '>';
    });
    await Promise.anyof( $timeout, $user );
    if $str eq 'q' {
        last;
    }
    say "[$str]";
}

【问题讨论】:

    标签: asynchronous promise user-input raku


    【解决方案1】:

    这是因为您正在与 prompt 进行错误调用,该调用位于已关闭不同变量 $str 的承诺中。第二次及以后调用prompt 块,等待第一次调用完成。但是接收第一次调用的值的$str超出了范围,所以什么也没有发生。

    这听起来很奇怪,但是当我更全面地剖析它时,你可以运行一个实验来帮助你的直觉:运行脚本,等待超时,然后快速连续输入两次q。脚本在第二个之后退出。为什么?

    在第一个循环中,我们声明了一个变量$str,我将其命名为“$str number 1”,并创建一个Promise,它在$str number 1 上结束并调用promptprompt 附加到 STDIN 并且在看到换行符之前不会返回。当超时到期时,对prompt 的调用不会中断。它仍在运行。还在等待。即使变量$user 即将超出范围,它所附加的promise(我们称之为$userpromise 1)仍然有效。

    在第二个循环中,我们声明了一个新变量 $str(“$str number 2”),创建一个关闭 itPromise,然后再次调用 prompt。但是对prompt 的另一个调用仍在使用STDIN,因此新调用阻塞并等待STDIN 可用。如果您现在输入一些内容,它将通过对 prompt 的原始调用可见,该调用附加到 $user promise 1 并在 $str 编号 1 上关闭。

    $str 数字 1 在prompt 返回时更新,但这并不重要,因为您不再查看它。 if $str eq 'q' 条件将检查 $str 数字 2,因为这是在当前循环中声明的变量。

    第二次调用prompt 然后立即要求输入,如果你在超时到期之前输入q,它会更新它关闭的$str 的版本,$str 编号 2。因为那是您的条件正在检查一个,循环终止。

    每次超时都会启动一个新的prompt 而不会终止旧的,这意味着用户键入的输入永远不会附加到您正在检查的同一个$str。即使您检查原始变量,对prompt 的后续调用仍然会发生,并且即使在执行离开块后也会继续提示。

    由于prompt 没有办法指定超时,Raku 也没有办法“杀死”预定的Promises,我认为你无法用prompt 解决这个问题。

    【讨论】:

      【解决方案2】:

      此代码中的逻辑问题是超时 Promise 在 5 秒后触发,即使有人在之前的迭代中输入了某些内容。所以它会在看似随机的时间设置$str

      有一个简单的解决方案:只要确保您在超时代码中指定$str(如果已设置):

      $str //= 'Timeout';
      

      对于本示例,这并不重要,但通常您不希望代码随意执行,因此最好实际停用Promise。不幸的是,你不能用Promise 接口来做到这一点。但Promise.in 方法实际上是ThreadPoolScheduler.cue 方法的包装器,确实返回一个Cancellation 对象(https://docs.raku.org/routine/cue)。

      【讨论】:

      • 当我将示例的第 6 行替换为 $str //= 'Timeout' 时,我看不到脚本结果有任何变化。
      • 那么也许您应该更准确地描述脚本的结果?
      • 触发超时后,q 的用户输入不再退出脚本,即使使用 $str //= 'Timeout'
      猜你喜欢
      • 2013-10-15
      • 1970-01-01
      • 1970-01-01
      • 2017-04-23
      • 2020-06-26
      • 2018-04-02
      • 2022-10-01
      • 2015-12-17
      • 1970-01-01
      相关资源
      最近更新 更多