首页 > 解决方案 > 超时的用户输入无法按预期工作

问题描述

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

#!/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]";
}

标签: asynchronouspromiseuser-inputraku

解决方案


这是因为您正在与错误的通话通话prompt,这是在一个已关闭不同变量的承诺中$str。第二个和以后的调用prompt阻塞,等待第一个调用完成。但是$str接收第一个调用的值超出了范围,所以什么也没有发生。

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

在第一个循环中,我们声明一个变量$str,我将其称为“$str数字 1”,并创建一个Promise关闭$str数字 1 并调用prompt. prompt附加到STDIN并且在看到换行符之前不会返回。当超时到期时,该调用prompt不会中断。它仍在运行。还在等待。$user即使变量$user即将超出范围,它所附加的承诺(我们称之为承诺 1)仍然有效。

在第二个循环中,我们声明一个新变量$str(“$str数字 2”),创建一个Promise关闭的变量,然后再次调用prompt。但另一个调用prompt仍在使用STDIN,因此新调用阻塞并等待STDIN变为可用。如果你现在输入一些东西,它会被原来的调用看到prompt,它附加到$user承诺 1 并关闭了$str数字 1。

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

对 then 的第二次调用prompt立即要求输入,如果您q在超时到期之前输入,它会更新$str它关闭的版本,$str编号 2。由于这是您的条件正在检查的版本,因此循环终止。

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

由于prompt没有办法指定超时并且 Raku 没有办法“杀死”预定Promises,我不认为你可以用prompt.


推荐阅读