Source: lib/util/cancelable_chain.js

  1. /**
  2. * @license
  3. * Copyright 2016 Google Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. goog.provide('shaka.util.CancelableChain');
  18. goog.require('goog.asserts');
  19. goog.require('shaka.util.Error');
  20. /**
  21. * A Promise-based abstraction that creates cancelable Promise chains.
  22. * When canceled, subsequent stages of the internal Promise chain will stop.
  23. * A canceled chain is rejected with a user-specified value.
  24. *
  25. * A CancelableChain only supports linear Promise chains. Chains which branch
  26. * (more than one then() handler chained to a particular stage) are not
  27. * supported. You will not be prevented from treating this as if branching
  28. * were supported, but everything will be serialized into a linear chain.
  29. * Be careful!
  30. *
  31. * @constructor
  32. * @struct
  33. */
  34. shaka.util.CancelableChain = function() {
  35. /** @private {!Promise} */
  36. this.promise_ = Promise.resolve();
  37. /** @private {boolean} */
  38. this.final_ = false;
  39. /** @private {boolean} */
  40. this.complete_ = false;
  41. /** @private {boolean} */
  42. this.canceled_ = false;
  43. /** @private {shaka.util.Error} */
  44. this.rejectionValue_;
  45. /** @private {function()} */
  46. this.onCancelComplete_;
  47. /** @private {!Promise} */
  48. this.cancelPromise_ = new Promise(function(resolve) {
  49. this.onCancelComplete_ = resolve;
  50. }.bind(this));
  51. };
  52. /**
  53. * @param {function(*)} callback
  54. * @return {!shaka.util.CancelableChain} the chain itself.
  55. */
  56. shaka.util.CancelableChain.prototype.then = function(callback) {
  57. goog.asserts.assert(!this.final_, 'Chain should not be final!');
  58. this.promise_ = this.promise_.then(callback).then(function(data) {
  59. if (this.canceled_) {
  60. this.onCancelComplete_();
  61. return Promise.reject(this.rejectionValue_);
  62. }
  63. return Promise.resolve(data);
  64. }.bind(this));
  65. return this;
  66. };
  67. /**
  68. * Finalize the chain.
  69. * Converts the chain into a simple Promise and stops accepting new stages.
  70. *
  71. * @return {!Promise}
  72. */
  73. shaka.util.CancelableChain.prototype.finalize = function() {
  74. if (!this.final_) {
  75. this.promise_ = this.promise_.then(function(data) {
  76. this.complete_ = true;
  77. return Promise.resolve(data);
  78. }.bind(this), function(error) {
  79. this.complete_ = true;
  80. if (this.canceled_) {
  81. this.onCancelComplete_();
  82. return Promise.reject(this.rejectionValue_);
  83. }
  84. return Promise.reject(error);
  85. }.bind(this));
  86. }
  87. this.final_ = true;
  88. return this.promise_;
  89. };
  90. /**
  91. * Cancel the Promise chain and reject with the given value.
  92. *
  93. * @param {!shaka.util.Error} reason
  94. * @return {!Promise} resolved when the cancelation has been processed by the
  95. * the chain and no more stages will execute. Note that this may be before
  96. * the owner of the finalized chain has seen the rejection.
  97. */
  98. shaka.util.CancelableChain.prototype.cancel = function(reason) {
  99. if (this.complete_) return Promise.resolve();
  100. this.canceled_ = true;
  101. this.rejectionValue_ = reason;
  102. return this.cancelPromise_;
  103. };