Waiting on API data

Hi all!

This is my first post, so let me start by saying AWESOME FRAMEWORK!

I’ve been working on an app with some very complex logic and Yii has come through with flying colors.

A huge thanks to those that contribute on this forum, it an invaluable resource.

So here’s my question:

In my app a user submits a form, the app sends out a call to a data provider via an API, the next page the user sees is populated by json data returned from the API.

The data provider may take anywhere from a few seconds to a few minutes to return the data, when the data is returned it is stored in an AR table.

What is the best way to "hold" the user until the data is returned?

  1. At first I thought ajax would be great for this, but its totally new to me and I have not found a way to make an ajax button to display "loading…" while checking to see when the field is populated in the DB by the API, then once populated it would show "Report ready, click here".

  2. Alternatively I could create a view that shows a "data loading" message and refreshes to check if the data has been returned every 5 seconds, and if so redirects to the proper view?

  3. I feel like their must be a better (more efficient) way to do this, any suggestions are appreciated!

Thanks,

Ian

Hello and welcome.

The thing that comes to my mind is SSE (Server-Sent Events), it’s more a client-side feature that calls a resource at a fixed interval. I’ve recently “discovered” it, made some tests and it’s cool and easy to use.

I have for instance internal messaging, and I want to display a message as soon as the user receives it (well technically I’m checking at an interval of 10 seconds). The idea is along these lines:

In the view:


<?php

Yii::app()->clientScript->registerScript('message-update', '

if(typeof(EventSource) !== "undefined") {

    var source = new EventSource("' . CController::createUrl('site/getMessage') . '");

    source.onmessage = function(event) {

        $("#message").prepend(event.data);

    };

}

else {

    $("#message").replaceWith("<div class=\"flash-notice\">Sorry, your browser doesn\'t support SSE. Hint: replace it with a real one :-)</div>");

}

', CClientScript::POS_READY);

?>

<div id="message"></div>

Controller:


public function actionGetMessage()

{

    $messageList = Message::model()->findAll(array('condition' => 'userId = :myId AND new = 1', 'order' => 'id DESC', 'params' => array(':myId' => Yii::app()->user->_id)));

    header('Content-Type: text/event-stream');

    header('Cache-Control: no-cache');

    echo "retry: 10000\n"; // tell the browser to retry after 10s

    if(count($messageList)) {

        foreach($messages as $key => $message) {

            echo "data: <p>$message</p>\n";

        }

        //here an update query in order to flag the now retrieved messages (new = 0)

    }

    flush();

}

In your case, you’d perform your test in the getMessage action. If the data is ready, you’d echo “Report ready” enclosed in the relevant link, otherwise, you’d echo “Still loading…” for instance.

I hope it helps. There surely are other ways to achieve that.

Hi Bennouna,

This is VERY cool and I appreciate you sharing it!

I would LOVE to use Server-Sent Events but from what I can tell they are not supported yet by Internet Explorer and that represents a big portion of our intended users…

Have you tested it with IE?

Thanks!

No I haven’t tested it in IE…

Edit: IE and FF < 6 don’t support SSE out of the box. But… tada… There’s a polyfill

Browser support:

IE 8+, Firefox 3.5+, Chrome 6+, Safari 5+, Opera 12+

And this gives my first wiki.

I’d like to thank bennouna for his server side events wiki, SSI will be an awesome solution when its supported by all major browsers.

Until then I have still have my original problem of a holding page for the user that will forward them on to the results after the callback from my data provider is complete, anywhere from a few seconds to a few minutes.

Right now I have a dedicated holding page that refreshes using javascript every 5 seconds, checks the AR to see if the data has arrived and if so forwards them on.

It’s very hackey and looks like garbage as it refreshes the whole page every 5 seconds until the data has arrived.

There has got to be a better way to do this, any help is really appreciated!

Thanks,

Ian