I want to display the results of some rather slow calculations on a webpage. While busy, some message is shown, and the webpage is updated when finished.
- Simple solution using repetitive page refreshes.
:- use_module(library(http/http_server)).
:- use_module(library(main)).
:- initialization(main, main).
main(_Argv) :-
http_server([port(8001)]),
thread_create(solve, _, []),
thread_get_message(quit).
:- http_handler(root(.), home, []).
home(_Request) :-
reply_html_page(
[ title("Not pretty"), \refresh ],
\status).
refresh -->
{ result(_) },
!.
refresh -->
html(meta(['http-equiv'(refresh), content(2)])).
status -->
{ result(R) },
!,
html(p("Result is ~w"-R)).
status -->
html(p("Still busy")).
:- dynamic result/1.
solve :-
sleep(10),
assert(result(42)).
Invoke swipl refresh.pl
and then open http://localhost:8001/ in your browser.
- Nice solution that sends a refresh message via a websocket.
:- use_module(library(http/websocket)).
:- use_module(library(http/http_server)).
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/html_write)).
:- use_module(library(http/js_write)).
server :-
thread_create(solve, _, [alias(solver)]),
http_server([port(8001)]).
:- http_handler(root(wait),
http_upgrade_to_websocket(wait, []), [spawn([])]).
wait(Socket) :-
thread_wait(result(_), [wait_preds([+(result/1)])]),
ws_send(Socket, websocket{data:"refresh", format:string, opcode:text}).
:- http_handler(root(.), home, []).
home(_Request) :-
reply_html_page(
[ title("Pretty"), \refresh ],
\status).
refresh
--> { result(_) },
!.
refresh
--> js_script({|javascript||
var connection;
function openWebSocket()
{
connection = new WebSocket("ws://" + window.location.host + "/wait");
connection.onmessage = function(e)
{
if(e.data == 'refresh')
{
location.reload();
}
}
}
window.addEventListener("DOMContentLoaded", openWebSocket, false);
|}).
status
--> { result(R) },
!,
html(p("Result is ~w"-R)).
status
--> html(p("Still busy")).
:- dynamic result/1.
solve :-
sleep(20),
assert(result(42)).
Is there anything I can improve (other than the turbopascalian indentation)?
Edit: Changed thread_join/1 to thread_wait/2 to allow for multiple requests within the busy time. The result is now available after 20 s. If the browser is closed and reopened again, we get error messages about broken pipes. How do I avoid or catch/3 these?