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

Greetings,

i am working on a program that is running several things through a web interface and need to tell the user to wait for the long opperations to complete.
i have a bit of code which looks basically like this

&html_start; &do_long_opp; .... sub html_start { .... print "This is gonna take a hellaofa long time<br>\n"; }
at the end of html_start i have a print statement telling the user to wait as this will take a while, but it doesnt show any of the page content other then the bg color until do_long_opp has finished.... well most of the time, sometimes it does it the way i want (and a do_long_opp can take upto 1 minute to run i really need to tell people to wait and not give up hope)
so, any thoughts on how to make this do things that way, with the displaying and then the long things that take forever?
jcpunk

by the way thanks for all the help that was, is, and will be

Replies are listed 'Best First'.
•Re: displaying output at the correct moment
by merlyn (Sage) on Jun 23, 2003 at 16:27 UTC
      Randal's meathods are clean and work well. Take a look at these two links he submitted -- they will do what you are after.

      -Waswas
Re: displaying output at the correct moment
by chromatic (Archbishop) on Jun 23, 2003 at 16:28 UTC

    This is one case where disabling buffering on STDOUT can help you.

    $| = 1;
Re: displaying output at the correct moment
by Coplan (Pilgrim) on Jun 23, 2003 at 17:04 UTC
    Buffers...the solution to end all.

    I have a web engine that I wrote...and I do error pages in much the same manner that you want to do your "wait" page. The trick is to gather ALL the content of the page prior to printing it out.

    What I would do is put everything into some sort of buffer in this manner:

    # assume this is a snippet from a fully functional, declared, stricted + script my $buffer; $buffer .= "content\n<br>\n"; #or for long sets: $buffer .= <<END Content <br> More content <br> END
    Then I have a subroutine to print the code. So my main script looks like this (very simplified):

    #!/usr/bin/perl -t use strict; include subroutines.pl; # I always put my subs for webapps in one pla +ce...and not in the main script. my $header = getheader(); my $footer = getfooter(); my $content = getcontent(); # This is where you'd run a bunch of chec +ks to see what you actually need print $header; print $content; print $footer; #eof

    Now obviously...if you need to do a "waiting" screen much like you do...you'll need to use a meta tag to set the refresh. that will need to go into the header. So somehow figure out a way for the getheader() subroutine to check if it needs a refresh, and then refresh it.

    Hope that helps.

    --Coplan

Re: displaying output at the correct moment
by Lost_ego (Novice) on Jun 23, 2003 at 16:22 UTC
    I can not offer any great solutions yet. I am working on the same issue just ina different context. The answers I have found so far are bleak. All my looking so far has turned up the same answer: the PRINT function is going to wait until the parent method is done before executing. I will let you know if I find a way arounf the problem.
Re: displaying output at the correct moment
by artist (Parson) on Jun 23, 2003 at 16:40 UTC
    A solution which may work for you case:
    Divide your script into 2: Once you finish the 'init' script, display the message that real-data is on the way and it can take some time. Changing algorithm to 'get' data faster would always be a better way but if it really takes time, then you require patient audience for your application.

    artist

Re: displaying output at the correct moment
by hardburn (Abbot) on Jun 23, 2003 at 16:36 UTC

    The way you're doing it now will be very dependant on the client. I've noticed IE usually renders the page as it comes in and moves stuff around if necessary. Netscape/Mozilla like to wait until all the HTML has been downloaded.

    Also, make sure you shut off buffered output, like this:

    $| = undef;

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

      Im not familiar with setting
      $| = undef
      My understanding was that there are only 2 buffering behaviours, and they are based on the truth value of $|
      So, $| = undef would evaluate to false, the same as the default value of $| = 0
      If $| is true, the output buffer is flushed after each output operation (print, printf, write). If $| is false, block buffereing occurs.
      What am i missing?

      Update:fixed a minor typo - i had $\ in place of $| in one place.

        Oops, you're right. I should have said $| = 1;.

        ----
        I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
        -- Schemer

        Note: All code is untested, unless otherwise stated