Eingabefelder

Tabellen

Drucktasten

Meldungen

Baum

Langtext

keepAlive

Taglib Demo: keepAlive

Eine Seite am Leben erhalten
Langdauernde Requests sollten Sie nach Möglichkeit aus Ihrer Web-Anwendung verbannen. Wenn es länger dauernde Operationen als Folge von Benutzereingaben gibt, lagern Sie diese besser in die Hintergrundverarbeitung aus.

Wenn Sie Antwortzeiten von 20 Sekunden oder mehr für einen Request haben, kann Ihnen der Browser-Timeout einen Streich spielen. Um dies zu verhindern, gibt es das Element <z:keepAlive>.

Das <z:keepAlive> hält eine Seite nach Druck auf einen Button (genauer: nach Ausführen der genericSubmit()-Funktion) am Leben, indem sie nach Ablauf von 20 Sekunden mittels der Javascript-Funktion setInterval() regelmässig einen Request auf eine spezielle, im ICM Server Cache gepufferte Seite ausführt (also einen "Herzschlag").


Beispielcode
Der untenstehende Test-Button führt die javascript-Funktion void() und damit eigentlich gar nichts aus. Das macht ihn zum idealen Testkandidaten für einen "Langsamläufer". Denn eine langsamlaufende Server-Applikation verhält sich für einige Zeit genauso wie void(): Sie macht nichts!

<z:keepAlive/>
<z:button fcode="dummy" href="javascript:void(0)" text="Test"/>

Nach Druck des Buttons sollte nach ca. 20 Sekunden in der Statuszeile die folgende Meldung erscheinen.


Demo
Test

Anmerkungen
Wenn Sie sich den Quelltext ansehen, bemerken Sie, dass das <keepAlive> folgendes rendert:

<script type="text/javascript">
if (typeof window.autorefreshURL != "undefined") autorefreshURL = "../zsrs/refresh.do?timeout=20";
</script>
<iframe src="" name="autorefresh" scrolling="no" style="display:none" width="0" height="0"></iframe>

Sie können sich fragen, wann denn das src Attribut des versteckten iframe mit der autorefreshURL abgefüllt wird. Dies geschieht in der Funktion checkBusy(), die beim Betätigen eines Buttons im allgemeinen aufgerufen wird, um bei ungeduldigem Klickverhalten zu verhindern, dass Requests mehrfach versendet werden. Diese Funktion hat in der SRS-Anwendung, aus der dieses Tag stammt, die folgende Form. Beachten Sie den setTimeout, mit dem die autorefreshURL verzögert in den iframe gesetzt wird.

function checkBusy( ) {
  if (isBusy) {
    alert(busyWarning);
    return false;
    }
  else {
    isBusy = true;
    if (document.autorefresh)
       autorefreshTimer = window.setTimeout( 'document.getElementsByName("autorefresh")[0].setAttribute("src",autorefreshURL);', 20000);
    return true;
    }
  }
Sobald das src Attribut einmal umgesetzt ist, wird die Seite in den versteckten iframe geladen. Sie enthält aber eine "refresh" Angabe im HTTP Header:

<head>
    <meta http-equiv="refresh"
          content="20 ; URL=refresh.do?interval=20 ">
  </head>

Aus dieser Angabe folgt, dass nach dem einmaligen Laden der Seite diese immer wieder neu abgefragt wird. Das hat den gewünschten Effekt, dass die Verbindung zum Server auch für die Hauptseite gehalten wird.

Übrigens ist es zwar sinnvoll, den Controller refresh.do serverseitig zu puffern, um Systemlast zu reduzieren; Sie dürfen aber keine clientseitige Verfallszeit angeben - sonst machen Sie sich den gewünschten Effekt zunichte. Wenn der Request aus dem Cache des Browsers bedient werden kann, nimmt dieser ja keine Verbindung mehr zum Server auf.

Das Beispiel funktioniert zur Zeit nur im Context des Retail Store - was für unsere Demoseite aber lediglich bedeutet, dass in der HTTP-Antwort ein temporäres Cookiefeld filiale=2700 gesetzt wird. (Grund ist, dass der für den Inhalt des <iframe> zuständige Controller refresh.do von der Basisklasse des Retail Store erbt (ZCL_CO_SRS)).