[plt-scheme] Tracking progress in Web servlets
Here's a technique I discovered while writing the new version of Help
Desk. Ultimately, I ended up not using the technique, but I think it
may be useful in other situations.
Suppose you have a PLT Web servlet that performs some extended
computation. Therefore, you want somehow to show the user that progress
is being made. One way would be to call Javascript code in the servlet
-- but who wants to do that?
Web continuations allow you to suspend the extended computation in order
to send some HTML back to the browser. In the usual examples of Web
continuations, the user hits a "Submit" button to get on with the
suspended computation. But we want to show progress without user
intervention. HTML gives us the mechanism for emulating hitting a
"Submit" button; it's the Netscape-invented META redirection.
As an example, suppose our extended computation is just a loop that
increments a counter. Each time around the loop, we display the current
value of the counter via send/suspend:
(let loop ([n 0])
(send/suspend
(lambda (k)
`(HTML
(HEAD
(META ((HTTP-EQUIV "refresh")
(CONTENT ,(string-append "1,URL=" k)))))
(BODY
"The current value of n is: "
,(number->string n)))))
(unless (> n 10)
(loop (add1 n))))
The META refresh resumes the loop automatically. The "1" indicates a
one second delay for the redirection, so we can actually view the page.
Otherwise, it goes by too fast to see.
To make a complete servlet out of this, you need to wrap it inside the
usual unit/sig, and finish with a suitable response. Something like
(require (lib "unitsig.ss")
(lib "servlet-sig.ss" "web-server"))
(unit/sig ()
(import servlet^)
[ loop code from above ]
`(HTML
(BODY "Done!")))
Sure, this isn't deep; it's kind of fun, though.
-- Paul