Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

A delay effect...

by kiat (Vicar)
on Dec 30, 2001 at 19:20 UTC ( [id://135243]=perlquestion: print w/replies, xml ) Need Help??

kiat has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

How do I achieve a delay effect in perl cgi? Specifically, say, I want to be able print something after a pause of two seconds. I have not been able to do that with 'sleep'.

#pseudocode if ($guess == 1234) { wait_for_two_seconds; print "Congratulations!<br>\n"; }
Happy New Year to all :)

kiat

Replies are listed 'Best First'.
Re: A delay effect...
by Beatnik (Parson) on Dec 30, 2001 at 21:21 UTC
    The fact that you want to pause in a CGI process strikes me as odd since CGI data is usually sent in a complete stream. The buffer flushing solution provided above seems like the most plausible one, altho your request is REALLY weird. Buffer flushing with CGIs is usually included when larger files are being generated.

    Another, non-sleep method would be to put a meta tag with a refresh that redirects to a congrats page.

    Altho there is more than one way to do it, using sleep isn't probably one of those ways :)

    Greetz
    Beatnik
    ... Quidquid perl dictum sit, altum viditur.
Re: A delay effect...
by simon.proctor (Vicar) on Dec 30, 2001 at 19:39 UTC
    Another simple method is to use select, ie:

    select(undef undef undef, 2);
    You can also use signals:

    eval { local $SIG{'ALRM'} = sub{die 'timesup';}; alarm 2; # Now do something as a pause while(1) { select(undef,undef,undef,0.01); } alarm 0; }; if($@ =~ 'timesup') { # Call timeout code }


    On the face of it, you gain nothing in the second example. However, you can use this to timeout pieces of code should you not want to hang around forever. Gaining a lock on a file for example.

    There are some platform issues using SIG{ALRM}, alarm() and select() but you should be ok on most platforms.

    HTH
    Simon

    PS: I was eating toast when I posted this so please excuse any typos :P
Re: A delay effect...
by unb0rn (Scribe) on Dec 30, 2001 at 19:29 UTC
    maybe
    sleep(2);
    ? And make sure autoflushing ($|++;) is active!
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: A delay effect...
by Juerd (Abbot) on Dec 30, 2001 at 19:49 UTC
    I want to be able print something after a pause of two seconds. I have not been able to do that with 'sleep'.
    That's weird, because that's what sleep is for.
    sleep 2 tells perl to wait for two seconds.

    select's 4-argument form provides for another way of sleeping. This can also handle floating point number of seconds like 2.5 (you could also use Time::HiRes for that).

    2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

      Hi Juerd,

      Yes, there is indeed a pause of two seconds. But say I have two print statements and I want the pause to come between them, is that possible?

      print "Congrats!<br>"; sleep 2; print "You guessed you it!";
      kiat
        UPDATE: This is my 100th post! :))

        Yes, but think about buffering. Perl won't flush it's buffer until it sees a newline.
        You have no \n after the <br>, so this is what happens:
        1. perl fills the buffer
        2. perl sleeps for two seconds
        3. perl appends to the buffer, and then flushes it because the end of the script is reached.
        Which of course is not what you want.

        You could put a \n after the <br>, or turn on the autoflush using $| = 1 (often seen obfuscated as $|++).

        print "First<br>\n"; sleep 2 print "Second\n"; ### $| = 1; print "First<br>"; sleep 2; print "Second";


        I recommend the newline solution, because HTML doesn't care about the newline being there, and autoflushing decreases performance.

        Information about $| and many other special variables can be found in perlvar.

        2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

        You could use NPH (non-parsed headers), which lets you send multiple pages on one request. Check this silly page for an example (delays 10 seconds).

        There were some tricks. The main one was I had to do use CGI qw(-oldstyle_urls) to make it work with Netscape 4.x. Basically, here is the way to do it:

        use CGI qw(-oldstyle_urls); my $q = new CGI; # ... if ($q->param('last')) { last_page($q); } else { next_page($q); } sub next_page { # ... $url = $q->url('-query' => 1); $last = ($url =~ /\?/) ? '&last=1' : '?last=1'; # Here is the delay, 10 seconds print $q->header('-Refresh' => "10;URL=$url$last"), # print the rest of the 1st page here... } sub last_page { # ... print $q->header(), # etc... }
Re: A delay effect...
by kiat (Vicar) on Dec 30, 2001 at 19:45 UTC
    Hi unb0rn,

    How do I make the autoflusing feature active?

    kiat
      To set the autoflush, just set the magic variable $| to 1. I used $|++ to increment it, because it's default value is 0, or autoflush turned off.

      Autoflush means that Perl sends the output of print's in time they are called. When it's off, Perl puts the print's output in a temporary buffer, and sends the print's output in blocks to the screen/client/etc.

      . Just another not-perfect-but-trying-to-be-legible answer 8-)
      Well you can use standard IO modules to do it in an OO fashion but the simplest (and most common in old scripts I would argue) is

      $|++;


      This increments the $| variable. To learn more take a look at the perlvar man page.
Re: A delay effect...
by cLive ;-) (Prior) on Dec 31, 2001 at 06:58 UTC
    I wouldn't use Perl for this - I'd use JavaScript.

    The main reason being that, odds are these days that you'll be doing this in an HTML table, and a table won't render until the whole thing is received by the browser (and until contained images are received if IMG tags don't contain valid height and width attributes).

    So all it will do is slow the page rendering down.

    If you are out of a table, you can get away with sleep(2), $|++ at the beginning of the script, and including a \n in the print statement before the sleep.

    But, please ask yourself if this is really the best way to go...

    .02

    cLive ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://135243]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2024-04-19 22:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found