UNPKG

@cross-border-bridge/data-channel

Version:
180 lines (179 loc) 6.5 kB
// Copyright © 2017 DWANGO Co., Ltd. var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; /** * データ種別コード */ var DATA_TYPE_PUSH = 1; var DATA_TYPE_REQUEST = 2; var DATA_TYPE_RESPONSE = 3; var DATA_TYPE_ERROR = 4; /** * DataChannel内部エラー */ var DataChannelError = (function (_super) { __extends(DataChannelError, _super); function DataChannelError() { _super.apply(this, arguments); } return DataChannelError; })(Error); exports.DataChannelError = DataChannelError; /** * DataBus上で単純なリクエスト&レスポンス機構を提供する。 */ var DataChannel = (function () { function DataChannel(dataBus) { this._handler = undefined; this._handlers = []; this._tagCount = 0; this._waitingCallbacks = {}; this._timeoutObjects = {}; this._dataBus = dataBus; } /** * DataChannelを破棄する際に実行する。 * このメソッドを実行するとすべてのハンドラが解放され、レスポンス待ちの処理についてはエラーが返る。 */ DataChannel.prototype.destroy = function () { var _this = this; if (!this._dataBus) return; this.unregister(); this._dataBus = undefined; this._handlers = undefined; Object.keys(this._waitingCallbacks).forEach(function (tag) { var error = new Error("plugin channel destroyed."); error.type = "Closed"; _this.processCallback(tag, error); }); this._waitingCallbacks = undefined; }; /** * このDataChannelが既に破棄されたかどうかを返す * * @return 破棄されていればtrue、されていなければfalse */ DataChannel.prototype.destroyed = function () { return !this._dataBus; }; /** * メッセージハンドラの登録を行う * * @param handler メッセージ受信時に実行されるハンドラ * @return ハンドラID */ DataChannel.prototype.addHandler = function (handler) { if (!Object.keys(this._handlers).length) { this.register(); } if (this._handlers.indexOf(handler) === -1) { this._handlers.push(handler); } }; /** * メッセージハンドラの解除を行う * * @param handlerId ハンドラ登録時に取得したハンドラID */ DataChannel.prototype.removeHandler = function (handler) { this._handlers = this._handlers.filter(function (h) { return h !== handler; }); if (!Object.keys(this._handlers).length) { this.unregister(); } }; /** * 登録されているすべてのメッセージハンドラの解除を行う */ DataChannel.prototype.removeAllHandlers = function () { if (!Object.keys(this._handlers).length) return; this._handlers = []; this.unregister(); }; /** * メッセージの送信を行う。 * * @param packet メッセージの実データ。フォーマットによって内容は自由に定義できる * @param callback メッセージに対してのレスポンスを受け取るコールバック。任意指定 * @param timeout レスポンスを待つ待機時間。待機時間を過ぎるとcallbackにtimeoutエラーが返る。未指定時はタイムアウトしない。 */ DataChannel.prototype.send = function (packet, callback, timeout) { var _this = this; if (timeout === void 0) { timeout = 0; } if (callback) { this.register(); var tag = this.acquireTag(); if (0 < timeout) { var timeoutObject = setTimeout(function () { var error = new Error("send timeout."); error.type = "Timeout"; _this.processCallback(tag, error); }, timeout); this._timeoutObjects[tag] = timeoutObject; } this._waitingCallbacks[tag] = callback; this._dataBus.send(DATA_TYPE_REQUEST, [tag, packet]); } else { this._dataBus.send(DATA_TYPE_PUSH, [packet]); } }; DataChannel.prototype.register = function () { var _this = this; if (this._handler) return; this._handler = function (dataType, data) { switch (dataType) { case DATA_TYPE_ERROR: { var error = new DataChannelError(); error.type = data[1]; _this.processCallback(data[0], error); return; } case DATA_TYPE_RESPONSE: _this.processCallback(data[0], null, data[1]); return; case DATA_TYPE_PUSH: _this._handlers.forEach(function (handler) { handler(data[0]); }); return; case DATA_TYPE_REQUEST: { var responseCallback = function (rpacket) { _this._dataBus.send(DATA_TYPE_RESPONSE, [data[0], rpacket]); }; _this._handlers.forEach(function (handler) { handler(data[1], responseCallback); }); return; } } }; this._dataBus.addHandler(this._handler); }; DataChannel.prototype.unregister = function () { if (!this._handler) return; this._dataBus.removeHandler(this._handler); this._handler = undefined; }; DataChannel.prototype.processCallback = function (targetTag, error, packet) { var callback = this._waitingCallbacks[targetTag]; if (callback) { delete this._waitingCallbacks[targetTag]; delete this._timeoutObjects[targetTag]; callback(error, packet); return true; } return false; }; DataChannel.prototype.acquireTag = function () { return "c:" + ++this._tagCount; }; return DataChannel; })(); exports.DataChannel = DataChannel;