Files
shaka-player/lib/util/cancelable_chain.js
T
Aaron Vaage 464a34ba4b Add events to Cancellable Chain
Added onComplete and onCancel events to CancellableChain so that someone
creating it can invoke their own code when it is cancelled or completed.

This is needed for the work on IDestroyable.

Change-Id: I5c274356e952ecbd43dd5e8809a6d4cb4e5e85c5
2017-11-27 23:44:10 +00:00

164 lines
4.4 KiB
JavaScript

/**
* @license
* Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
goog.provide('shaka.util.CancelableChain');
goog.require('goog.asserts');
goog.require('shaka.util.Error');
/**
* A Promise-based abstraction that creates cancelable Promise chains.
* When canceled, subsequent stages of the internal Promise chain will stop.
* A canceled chain is rejected with a user-specified value.
*
* A CancelableChain only supports linear Promise chains. Chains which branch
* (more than one then() handler chained to a particular stage) are not
* supported. You will not be prevented from treating this as if branching
* were supported, but everything will be serialized into a linear chain.
* Be careful!
*
* @constructor
* @struct
*/
shaka.util.CancelableChain = function() {
/** @private {!Promise} */
this.promise_ = Promise.resolve();
/** @private {boolean} */
this.final_ = false;
/** @private {boolean} */
this.complete_ = false;
/** @private {boolean} */
this.canceled_ = false;
/** @private {shaka.util.Error} */
this.rejectionValue_;
/** @private {function()} */
this.onCancelComplete_;
/** @private {!Promise} */
this.cancelPromise_ = new Promise(function(resolve) {
this.onCancelComplete_ = resolve;
}.bind(this));
/**
* Callbacks for when the chain completes successfully.
* @private {!Array.<!function()>}
*/
this.onComplete_ = [];
/**
* Callbacks for when the chain is cancelled.
* @private {!Array.<!function()>}
*/
this.onCancel_ = [];
};
/**
* @param {function(*)} callback
* @return {!shaka.util.CancelableChain} the chain itself.
*/
shaka.util.CancelableChain.prototype.then = function(callback) {
goog.asserts.assert(!this.final_, 'Chain should not be final!');
this.promise_ = this.promise_.then(callback).then(function(data) {
if (this.canceled_) {
this.onCancelComplete_();
return Promise.reject(this.rejectionValue_);
}
return Promise.resolve(data);
}.bind(this));
return this;
};
/**
* Finalize the chain.
* Converts the chain into a simple Promise and stops accepting new stages.
*
* @return {!Promise}
*/
shaka.util.CancelableChain.prototype.finalize = function() {
if (!this.final_) {
this.promise_ = this.promise_.then(function(data) {
this.complete_ = true;
// Tel everyone that is listening that the chain has completed.
this.onComplete_.forEach(function(callback) { callback(); });
return Promise.resolve(data);
}.bind(this), function(error) {
this.complete_ = true;
if (this.canceled_) {
this.onCancelComplete_();
return Promise.reject(this.rejectionValue_);
}
return Promise.reject(error);
}.bind(this));
}
this.final_ = true;
return this.promise_;
};
/**
* Cancel the Promise chain and reject with the given value.
*
* @param {!shaka.util.Error} reason
* @return {!Promise} resolved when the cancelation has been processed by the
* the chain and no more stages will execute. Note that this may be before
* the owner of the finalized chain has seen the rejection.
*/
shaka.util.CancelableChain.prototype.cancel = function(reason) {
if (this.complete_) return Promise.resolve();
this.canceled_ = true;
this.rejectionValue_ = reason;
// Tell everyone that is listening that the chain has been cancelled.
this.onCancel_.forEach(function(callback) { callback(); });
return this.cancelPromise_;
};
/**
* Add a callback to be called if the chain is canceled mid-execution. Calls to
* |onCancel| are accumulative.
*
* @param {!function()} callback
*/
shaka.util.CancelableChain.prototype.onCancel = function(callback) {
this.onCancel_.push(callback);
};
/**
* Add a callback to be called if the chain is completed. Calls to
* |onComplete| are accumulative.
*
* @param {!function()} callback
*/
shaka.util.CancelableChain.prototype.onComplete = function(callback) {
this.onComplete_.push(callback);
};