github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/themes/wind/static/libs/sockjs-client-1.1.0/lib/transport/receiver/jsonp.js (about)

     1  'use strict';
     2  
     3  var utils = require('../../utils/iframe')
     4    , random = require('../../utils/random')
     5    , browser = require('../../utils/browser')
     6    , urlUtils = require('../../utils/url')
     7    , inherits = require('inherits')
     8    , EventEmitter = require('events').EventEmitter
     9    ;
    10  
    11  var debug = function() {};
    12  if (process.env.NODE_ENV !== 'production') {
    13    debug = require('debug')('sockjs-client:receiver:jsonp');
    14  }
    15  
    16  function JsonpReceiver(url) {
    17    debug(url);
    18    var self = this;
    19    EventEmitter.call(this);
    20  
    21    utils.polluteGlobalNamespace();
    22  
    23    this.id = 'a' + random.string(6);
    24    var urlWithId = urlUtils.addQuery(url, 'c=' + encodeURIComponent(utils.WPrefix + '.' + this.id));
    25  
    26    global[utils.WPrefix][this.id] = this._callback.bind(this);
    27    this._createScript(urlWithId);
    28  
    29    // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
    30    this.timeoutId = setTimeout(function() {
    31      debug('timeout');
    32      self._abort(new Error('JSONP script loaded abnormally (timeout)'));
    33    }, JsonpReceiver.timeout);
    34  }
    35  
    36  inherits(JsonpReceiver, EventEmitter);
    37  
    38  JsonpReceiver.prototype.abort = function() {
    39    debug('abort');
    40    if (global[utils.WPrefix][this.id]) {
    41      var err = new Error('JSONP user aborted read');
    42      err.code = 1000;
    43      this._abort(err);
    44    }
    45  };
    46  
    47  JsonpReceiver.timeout = 35000;
    48  JsonpReceiver.scriptErrorTimeout = 1000;
    49  
    50  JsonpReceiver.prototype._callback = function(data) {
    51    debug('_callback', data);
    52    this._cleanup();
    53  
    54    if (this.aborting) {
    55      return;
    56    }
    57  
    58    if (data) {
    59      debug('message', data);
    60      this.emit('message', data);
    61    }
    62    this.emit('close', null, 'network');
    63    this.removeAllListeners();
    64  };
    65  
    66  JsonpReceiver.prototype._abort = function(err) {
    67    debug('_abort', err);
    68    this._cleanup();
    69    this.aborting = true;
    70    this.emit('close', err.code, err.message);
    71    this.removeAllListeners();
    72  };
    73  
    74  JsonpReceiver.prototype._cleanup = function() {
    75    debug('_cleanup');
    76    clearTimeout(this.timeoutId);
    77    if (this.script2) {
    78      this.script2.parentNode.removeChild(this.script2);
    79      this.script2 = null;
    80    }
    81    if (this.script) {
    82      var script = this.script;
    83      // Unfortunately, you can't really abort script loading of
    84      // the script.
    85      script.parentNode.removeChild(script);
    86      script.onreadystatechange = script.onerror =
    87          script.onload = script.onclick = null;
    88      this.script = null;
    89    }
    90    delete global[utils.WPrefix][this.id];
    91  };
    92  
    93  JsonpReceiver.prototype._scriptError = function() {
    94    debug('_scriptError');
    95    var self = this;
    96    if (this.errorTimer) {
    97      return;
    98    }
    99  
   100    this.errorTimer = setTimeout(function() {
   101      if (!self.loadedOkay) {
   102        self._abort(new Error('JSONP script loaded abnormally (onerror)'));
   103      }
   104    }, JsonpReceiver.scriptErrorTimeout);
   105  };
   106  
   107  JsonpReceiver.prototype._createScript = function(url) {
   108    debug('_createScript', url);
   109    var self = this;
   110    var script = this.script = global.document.createElement('script');
   111    var script2;  // Opera synchronous load trick.
   112  
   113    script.id = 'a' + random.string(8);
   114    script.src = url;
   115    script.type = 'text/javascript';
   116    script.charset = 'UTF-8';
   117    script.onerror = this._scriptError.bind(this);
   118    script.onload = function() {
   119      debug('onload');
   120      self._abort(new Error('JSONP script loaded abnormally (onload)'));
   121    };
   122  
   123    // IE9 fires 'error' event after onreadystatechange or before, in random order.
   124    // Use loadedOkay to determine if actually errored
   125    script.onreadystatechange = function() {
   126      debug('onreadystatechange', script.readyState);
   127      if (/loaded|closed/.test(script.readyState)) {
   128        if (script && script.htmlFor && script.onclick) {
   129          self.loadedOkay = true;
   130          try {
   131            // In IE, actually execute the script.
   132            script.onclick();
   133          } catch (x) {
   134            // intentionally empty
   135          }
   136        }
   137        if (script) {
   138          self._abort(new Error('JSONP script loaded abnormally (onreadystatechange)'));
   139        }
   140      }
   141    };
   142    // IE: event/htmlFor/onclick trick.
   143    // One can't rely on proper order for onreadystatechange. In order to
   144    // make sure, set a 'htmlFor' and 'event' properties, so that
   145    // script code will be installed as 'onclick' handler for the
   146    // script object. Later, onreadystatechange, manually execute this
   147    // code. FF and Chrome doesn't work with 'event' and 'htmlFor'
   148    // set. For reference see:
   149    //   http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
   150    // Also, read on that about script ordering:
   151    //   http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
   152    if (typeof script.async === 'undefined' && global.document.attachEvent) {
   153      // According to mozilla docs, in recent browsers script.async defaults
   154      // to 'true', so we may use it to detect a good browser:
   155      // https://developer.mozilla.org/en/HTML/Element/script
   156      if (!browser.isOpera()) {
   157        // Naively assume we're in IE
   158        try {
   159          script.htmlFor = script.id;
   160          script.event = 'onclick';
   161        } catch (x) {
   162          // intentionally empty
   163        }
   164        script.async = true;
   165      } else {
   166        // Opera, second sync script hack
   167        script2 = this.script2 = global.document.createElement('script');
   168        script2.text = "try{var a = document.getElementById('" + script.id + "'); if(a)a.onerror();}catch(x){};";
   169        script.async = script2.async = false;
   170      }
   171    }
   172    if (typeof script.async !== 'undefined') {
   173      script.async = true;
   174    }
   175  
   176    var head = global.document.getElementsByTagName('head')[0];
   177    head.insertBefore(script, head.firstChild);
   178    if (script2) {
   179      head.insertBefore(script2, head.firstChild);
   180    }
   181  };
   182  
   183  module.exports = JsonpReceiver;