Path: blob/trunk/third_party/closure/goog/net/streams/xhrnodereadablestream.js
2884 views
// Copyright 2015 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview adaptor of XhrStreamReader to the NodeReadableStream interface.16*/1718goog.provide('goog.net.streams.XhrNodeReadableStream');1920goog.require('goog.array');21goog.require('goog.log');22goog.require('goog.net.streams.NodeReadableStream');23goog.require('goog.net.streams.XhrStreamReader');24252627/**28* The XhrNodeReadableStream class.29*30* @param {!goog.net.streams.XhrStreamReader} xhrReader The XhrStreamReader31* object that handles the events of the underlying Xhr.32* @constructor33* @implements {goog.net.streams.NodeReadableStream}34* @struct35* @final36* @package37*/38goog.net.streams.XhrNodeReadableStream = function(xhrReader) {39/**40* @const41* @private {?goog.log.Logger} the logger.42*/43this.logger_ = goog.log.getLogger('goog.net.streams.XhrNodeReadableStream');444546/**47* The xhr reader.48*49* @private {!goog.net.streams.XhrStreamReader} the xhr reader.50*/51this.xhrReader_ = xhrReader;5253this.xhrReader_.setDataHandler(goog.bind(this.onData_, this));54this.xhrReader_.setStatusHandler(goog.bind(this.onStatusChange_, this));5556/**57* The callback map, keyed by eventTypes.58*59* @private {!Object<Array<function(!Object=)>>}60*/61this.callbackMap_ = {};6263/**64* The callback-once map, keyed by eventTypes.65*66* @private {!Object<Array<function(!Object=)>>}67*/68this.callbackOnceMap_ = {};69};707172/**73* @override74*/75goog.net.streams.XhrNodeReadableStream.prototype.on = function(76eventType, callback) {77var callbacks = this.callbackMap_[eventType];78if (!callbacks) {79callbacks = [];80this.callbackMap_[eventType] = callbacks;81}8283callbacks.push(callback);84return this;85};868788/**89* @override90*/91goog.net.streams.XhrNodeReadableStream.prototype.addListener = function(92eventType, callback) {93this.on(eventType, callback);94return this;95};969798/**99* @override100*/101goog.net.streams.XhrNodeReadableStream.prototype.removeListener = function(102eventType, callback) {103var callbacks = this.callbackMap_[eventType];104if (callbacks) {105goog.array.remove(callbacks, callback); // keep the empty array106}107108var onceCallbacks = this.callbackOnceMap_[eventType];109if (onceCallbacks) {110goog.array.remove(onceCallbacks, callback);111}112113return this;114};115116117/**118* @override119*/120goog.net.streams.XhrNodeReadableStream.prototype.once = function(121eventType, callback) {122var callbacks = this.callbackOnceMap_[eventType];123if (!callbacks) {124callbacks = [];125this.callbackOnceMap_[eventType] = callbacks;126}127128callbacks.push(callback);129return this;130};131132133/**134* Handles any new data from XHR.135*136* @param {!Array<!Object>} messages New messages, to be delivered in order137* and atomically.138* @private139*/140goog.net.streams.XhrNodeReadableStream.prototype.onData_ = function(messages) {141var callbacks =142this.callbackMap_[goog.net.streams.NodeReadableStream.EventType.DATA];143if (callbacks) {144this.doMessages_(messages, callbacks);145}146147var onceCallbacks =148this.callbackOnceMap_[goog.net.streams.NodeReadableStream.EventType.DATA];149if (onceCallbacks) {150this.doMessages_(messages, onceCallbacks);151}152this.callbackOnceMap_[goog.net.streams.NodeReadableStream.EventType.DATA] =153[];154};155156157/**158* Deliver messages to registered callbacks.159*160* Exceptions are caught and logged (debug), and ignored otherwise.161*162* @param {!Array<!Object>} messages The messages to be delivered163* @param {!Array<function(!Object=)>} callbacks The callbacks.164* @private165*/166goog.net.streams.XhrNodeReadableStream.prototype.doMessages_ = function(167messages, callbacks) {168var self = this;169for (var i = 0; i < messages.length; i++) {170var message = messages[i];171172goog.array.forEach(callbacks, function(callback) {173try {174callback(message);175} catch (ex) {176self.handleError_('message-callback exception (ignored) ' + ex);177}178});179}180};181182183/**184* Handles any state changes from XHR.185*186* @private187*/188goog.net.streams.XhrNodeReadableStream.prototype.onStatusChange_ = function() {189var currentStatus = this.xhrReader_.getStatus();190var Status = goog.net.streams.XhrStreamReader.Status;191var EventType = goog.net.streams.NodeReadableStream.EventType;192193switch (currentStatus) {194case Status.ACTIVE:195this.doStatus_(EventType.READABLE);196break;197198case Status.BAD_DATA:199case Status.HANDLER_EXCEPTION:200case Status.NO_DATA:201case Status.TIMEOUT:202case Status.XHR_ERROR:203this.doStatus_(EventType.ERROR);204break;205206case Status.CANCELLED:207this.doStatus_(EventType.CLOSE);208break;209210case Status.SUCCESS:211this.doStatus_(EventType.END);212break;213}214};215216217/**218* Run status change callbacks.219*220* @param {string} eventType The event type221* @private222*/223goog.net.streams.XhrNodeReadableStream.prototype.doStatus_ = function(224eventType) {225var callbacks = this.callbackMap_[eventType];226var self = this;227if (callbacks) {228goog.array.forEach(callbacks, function(callback) {229try {230callback();231} catch (ex) {232self.handleError_('status-callback exception (ignored) ' + ex);233}234});235}236237var onceCallbacks = this.callbackOnceMap_[eventType];238if (onceCallbacks) {239goog.array.forEach(onceCallbacks, function(callback) { callback(); });240}241242this.callbackOnceMap_[eventType] = [];243};244245246/**247* Log an error248*249* @param {string} message The error message250* @private251*/252goog.net.streams.XhrNodeReadableStream.prototype.handleError_ = function(253message) {254goog.log.error(this.logger_, message);255};256257258