curtis1000
12/10/2013 - 10:12 PM

An HTTP Stream Listener Model in Javascript. This object can listen to an http stream that doesn't close, and forward chunks of incoming dat

An HTTP Stream Listener Model in Javascript. This object can listen to an http stream that doesn't close, and forward chunks of incoming data to any subscribed listeners.

/**
 * @fileOverview HttpStreamModel Module
 * @version 1.0
 */

define(['jquery'], function($) {

    require(['bind']);

    'use strict';

    var url;

    var HttpStreamModel = {

        XHR_READY_STATE_REQUEST_RECEIVED: 2,
        listeners: [],

        setUrl: function(url) {
          url = url;  
        },

        openStream: function() {

            if (typeof window.XDomainRequest === 'undefined') {
                this._openStreamXHR();
            } else {
                this._openStreamXDR();
            }
        },

        /**
         * Legacy IE
         */
        _openStreamXDR: function() {
            try {
                var xdr = new XDomainRequest();
                xdr.open("GET", url);
                xdr.send();

                xdr.onload = function() {
                    // ... would only get here if the connection closes
                };

                xdr.onerror = function() {
                    // error handline
                };

                xdr.onprogress = function() {
                    this.setResponse(xdr.responseText);
                    this.parseResponse();
                    this.notifyListeners();
                }.bind(this);
            } catch (e) {
                this.log("[XDR] Exception: " + e);
            }

        },

        /**
         * Modern Browsers
         */
        _openStreamXHR: function() {
            var xhr = new XMLHttpRequest();

            xhr.onload = function() {
                // since our connection doesn't close, there's nothing to handle here
            };

            xhr.onerror = function() {
                // error handling
            };

            xhr.onreadystatechange = function() {
                try {
                    if (xhr.readyState > this.XHR_READY_STATE_REQUEST_RECEIVED) {
                        this.setResponse(xhr.responseText);
                        this.parseResponse();
                        this.notifyListeners();
                    }
                }
                catch (e){
                    // exception handling
                }
            }.bind(this);

            xhr.open("GET", url, true);
            xhr.send("Making request...");

        },

        setResponse: function(response) {
            this.response = response;
        },

        /**
         * The feed is not valid json, so we need to treat it as text, parse out the last object, and decode it to
         * an object
         */
        parseResponse: function() {
            var lastObjectIndex = this.response.lastIndexOf("{");
            var substring = $.trim(this.response.substring(lastObjectIndex)).replace(/(\r\n|\n|\r)/gm, "");
            if (substring.length) {
                try {
                    var latest = $.parseJSON(substring);
                    if (typeof latest !== 'undefined') {
                        this.latest = latest;
                    }
                } catch (e) {
                    // silent
                }

            }
        },

        notifyListeners: function() {
            if (typeof this.latest !== 'undefined') {
                for (var listener in this.listeners) {
                    if (typeof this.listeners[listener] === 'function') {
                        this.listeners[listener](this.latest);
                    }
                }
            }
        },

        addListener: function(listener) {
            if (typeof listener === 'function') {
                this.listeners.push(listener);
            }
        },

        log: function(msg) {
            if (window.XDomainRequest) {
                alert(msg);
            } else {
                console.log(msg);
            }
        }
    };

    return HttpStreamModel;
});