2

クライアント側のPerlScriptを使用するIE用の非常に小さなhtmlページを作成しました。スクリプトでは、TCPソケットを作成する別のプロセスを起動します。プロセスを起動した後、行が読み取られるときにdivの最後にHTMLを追加するリスナーを起動します。さらに、デバッグのために、各行が読み取られるときにアラートを追加しました。

問題は、行が読み取られるときにアラートがスポットにヒットすることですが、プロセスが終了するまでHTMLは更新されません。何故ですか?同じ動作を実現できるように、ページを強制的にレンダリングする方法はありますか?

ページは次のとおりです。

<html>
    <head>
        <title>Message Test</title>
        <script language=perlscript>
            use util;
            use Win32::Process;

            my $alreadyrunflag = 0;

            sub _write {
                $window->document->body->insertAdjacentHTML("beforeEnd", $_[0]);
            }

            sub go {
                _write("starting!<br/>");

                my $port = 12345;
                #//system("start /b /NORMAL perl C:/development/plslog/clitest2.pl $port");
                Win32::Process::Create(my $Proc, "C:/perl/bin/perl.exe", "perl clitest2.pl 12345", 1, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, "C:/development/plslog");
                $window->alert("Hi! started!");

                if (defined (my $INPUT = util::CreateClient($port))) {
                    while(defined (my $line = <$INPUT>)) {
                       _write($line);
                        sleep(3);
                    }
               }

               _write("ending!");
            }

            $window->setTimeout("go()",0);
        </script>
    </head>
    <body>
        <div id="content"></div>
    </body>
</html>

私は信じられないほどまばらなPerlScriptのオンラインドキュメントを見てきました。IEにページレンダリングを起動するように命令する方法、これらのhtml挿入に応答する方法などのヒントを探しています。

これを調査したところ、onloadの代わりに、divでonclickを使用すると、行が読み取られるときにレンダリングできることがわかりました。おそらく、適切なイベントを使用しておらず、サブルーチンが起動される前にページが完全にレンダリングされていませんか?私はここでIEに非常に不満を感じています(v.9)。

はい、これをコマンドラインの状況で使用すると、すべてが期待どおりに起動します。CreateServer / CreateClientは、クライアントとサーバーのIO :: Socket::INETの単なるラッパーです。

更新(@Oleg V. Volkovの回答に基づく):

goを変更し、行を読み取り、制御をブラウザーに戻してレンダリングする_read()関数を追加しました。大丈夫な仕事をしているようです。

sub _read() {
  my $port = shift;
  $INPUT = util::CreateClient($port) if ! $INPUT;
  if (defined (my $line = <$INPUT>)) {
    _write($line);
    $window->setTimeout("_read($port)", 0);
  }
  else {
    _write("Fin!");
  }
}
sub go() {
  _write("starting!<br/>");
  my $port = 12345;
  Win32::Process::Create(my $Proc, "C:/perl/bin/perl.exe", "perl clitest2.pl $port", 1, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, "C:/development/plslog");
  $window->alert("Hi! started!");
  $window->setTimeout("_read($port)", 0);
}

それはほぼリアルタイムの更新になるようです。

4

1 に答える 1

2

ほとんどの(すべてではないにしても)ブラウザは、ホストされているスクリプトプロセスから戻るまでページを再描画しません。一部の操作でデータの内部表現をリフローできますが、制御を戻すまでデータの再描画に時間を費やすことはありません。ブラウザが再描画できるようにするには、タスクをステップに分割し、スクリプトを使用して次のステップをスケジュールし、スクリプトから実行することでsetTimeout、たまに譲歩する必要がありreturnます。

sleep(3)あなたの特定のケースでは、とにかく何もしない場所を、3秒後に発生する次のループ反復のスケジューリングに置き換えることが最善の方法のように思われます。

于 2012-05-25T17:22:17.567 に答える