AjaxAction view helper for Zend Framework

Posted by web-rocker in Zend Framework

Bei größeren Webapplikationen kann es immer mal wieder vorkommen, das Inhalte oder ein Teilbereiche einer Webseite nicht spontan verfügbar sind. Ursachen dafür sind oft kalte Caches von Models oder die Latenzen die durch die Kommunikation mit extenen Webservices bedingt sind. Ich war es irgendwann Leid diese Wartezeiten zu einem Problem des Users machen zu müssen und habe einen kleinen View Helper entwickelt, der langlaufende Prozesse loskoppelt und das Ergebnis per AJAX nachliefert.

Im Prinzip wird die Webseite unvollständig an den User übermittelt und dann in seinem Webbrowser fertig gerendert.

Um die Problemstellung zu verdeutlichen habe ich einen ContentController geschrieben, dessen Geschwindigkeitsengpässe wohl keiner weiteren Erklärung bedürfen :-)

class ContentController extends Zend_Controller_Action
{
    public function getnavigationAction()
    {
        sleep(1);
        $this->view->assign('navi', 'This Navigation takes 1 second');
    }
    public function getcontentAction()
    {
        sleep(2);
        $this->view->assign('content', 'Delicious content takes 2 seconds');
    }
    public function gettweetsAction()
    {
        sleep(2);
        $twitter = new Zend_Service_Twitter_Search();
        $this->view->assign(
            'tweets',
            $twitter->search('php', array('lang' => 'en', 'rpp' => 5))
        );
    }
}

Dieser ContentController liefert Teilbereiche meiner Webseite aus. Eine Navigation, den Inhalt und einen Twitterstream. Aller Actions sind mit einer Zeitverzögerung von 1 oder 2 Sekunden ausgestattet, um den Vergleich deutlicher darstellen zu können.

Diese Teilbereiche fasse ich in der Index View, mit Hilfe des von Zend mitgelieferten Action View Helpers zusammen:

<div>
 <h1>old-school version</h1>
 <ul>
 <li><a href="/index/async">open the same page using AjaxAction helper</a></li>
 </ul>
 <h3>This is a REALLY expensive navigation</h3>
 <?php echo $this->action('getnavigation', 'content', null, array()); ?>
 <h3>This is the content</h3>
 <?php echo $this->action('getcontent', 'content', null, array()); ?>
 <h3>This is a cool result of a call to the Twitter-API</h3>
 <?php echo $this->action('gettweets', 'content', null, array()); ?>
</div>

Lade ich nur die Seite dauert es natürlich geschlagene 6 Sekunden, bis die Seite an den Webbrowser ausgeliefert wird.

Ersetze ich jetzt den View Helper Action durch AjaxAction und füge einen Parameter mit einem AJAX-Partial hinzu, das sich um die AJAX Magic kümmert, sieht meine View wie folgt aus:

<div>
 <h1>Welcome to the AjaxAction View Helper Demo</h1>
 <ul>
 <li><a href="/index/sync">open the oldschool version (synchronous)</a></li>
 </ul>
 <h3>This is a REALLY expensive navigation</h3>
 <?php echo $this->ajaxAction('getnavigation', 'content', null, array(), '_partials/ajax.phtml'); ?>
 <h3>This is the content</h3>
 <?php echo $this->ajaxAction('getcontent', 'content', null, array(), '_partials/ajax.phtml'); ?>
 <h3>This is a cool result of a call to the Twitter-API</h3>
 <?php echo $this->ajaxAction('gettweets', 'content', null, array(), '_partials/ajax.phtml'); ?>
</div>

Jetzt Rufe ich die Seite erneut auf:

Die komplette Seite konnte nun trotz der langlaufenden Prozesse unter 3 Sekunden, vollständig gerendert dargestellt werden.

Die Anpassung an das AJAX Framework der Wahl gestaltet sich einfach, es muss nur das Partial ajax.phtml angepasst werden. Hier mein Partial mit JQuery:

<div id="<?php echo $this->ajaxActionId ?>">
Content is beeing generated for You, please stand by...
</div>
<script type="text/javascript">
$('#<?php echo $this->ajaxActionId; ?>').load('<?php echo $this->ajaxActionUrl; ?>');
</script>

Schaut Euch einfach mal das Demoprojekt an, ich habe es komplett bei GitHub hochgeladen: AjaxAction-View-Helper-for-Zend-Framework

Dieser View Helper ist aber erst der Anfang! In Kürze werde ich ein FrontController Plugin mit dem tollen Namen ActionCache veröffentlichen. Es arbeitet Hand in Hand mit dem AjaxAction View Helper und ermöglicht ein hervorragend einfaches Caching von Teilbereichen und geringe Wartezeiten für User, die eine Seite aus einem kalten Cache abrufen.

Hier gehts weiter:
Artikel CacheAction Plugin For Zend Framework

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

  • Facebook
  • Twitter
  • Delicious
  • Digg
  • LinkedIn
  • Technorati
  • StumbleUpon
  • Reddit
  • RSS Feed
  • Google
  • Design Bump

4 Responses

  • Ben says:

    Hey,
    sehr nett – und so schön simpel. :)

    Wie sieht das denn mit einem Fallback für Leute/Browser ohne JS aus?
    Haben diese “Pech gehabt”, müssen diese auf eine extra “no-JS”-Seite gehen oder gibt es eine Möglichkeit, die ich gerade übersehe?

    mfg
    Ben

  • Pingback: CacheAction Plugin for Zend Framework - Web-Rocker

  • @ben In anbetracht der Tatsache das ungefähr 99,9% JavaScript unterstützen, habe ich das Fallback erst mal vernachlässigt.

    Es ist aber denkbar im ajax.phtml ein Div mit dem Hinweis das JS nicht unterstützt wird anzuzeigen und diesen dann mit JQuery für Browser mit JS auszublenden.

    Der Hinweis könnte einen Link enthalten, der einen “kein JS” Cookie setzt und die Seite noch mal aufruft. Der View Helper könnte darauf dann reagieren und synchron arbeiten.

    Ich baue das bei Gelegenheit mal ein, Danke für die Frage!



Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>