transaction.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // Copyright 2011 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Wrapper for an IndexedDB transaction.
  16. *
  17. */
  18. goog.provide('goog.db.Transaction');
  19. goog.provide('goog.db.Transaction.TransactionMode');
  20. goog.require('goog.async.Deferred');
  21. goog.require('goog.db.Error');
  22. goog.require('goog.db.ObjectStore');
  23. goog.require('goog.events');
  24. goog.require('goog.events.EventHandler');
  25. goog.require('goog.events.EventTarget');
  26. /**
  27. * Creates a new transaction. Transactions contain methods for accessing object
  28. * stores and are created from the database object. Should not be created
  29. * directly, open a database and call createTransaction on it.
  30. * @see goog.db.IndexedDb#createTransaction
  31. *
  32. * @param {!IDBTransaction} tx IndexedDB transaction to back this wrapper.
  33. * @param {!goog.db.IndexedDb} db The database that this transaction modifies.
  34. * @constructor
  35. * @extends {goog.events.EventTarget}
  36. * @final
  37. */
  38. goog.db.Transaction = function(tx, db) {
  39. goog.db.Transaction.base(this, 'constructor');
  40. /**
  41. * Underlying IndexedDB transaction object.
  42. *
  43. * @type {!IDBTransaction}
  44. * @private
  45. */
  46. this.tx_ = tx;
  47. /**
  48. * The database that this transaction modifies.
  49. *
  50. * @type {!goog.db.IndexedDb}
  51. * @private
  52. */
  53. this.db_ = db;
  54. /**
  55. * Event handler for this transaction.
  56. *
  57. * @type {!goog.events.EventHandler<!goog.db.Transaction>}
  58. * @private
  59. */
  60. this.eventHandler_ = new goog.events.EventHandler(this);
  61. // TODO(user): remove these casts once the externs file is updated to
  62. // correctly reflect that IDBTransaction extends EventTarget
  63. this.eventHandler_.listen(
  64. /** @type {!EventTarget} */ (this.tx_), 'complete',
  65. goog.bind(
  66. this.dispatchEvent, this, goog.db.Transaction.EventTypes.COMPLETE));
  67. this.eventHandler_.listen(
  68. /** @type {!EventTarget} */ (this.tx_), 'abort',
  69. goog.bind(
  70. this.dispatchEvent, this, goog.db.Transaction.EventTypes.ABORT));
  71. this.eventHandler_.listen(
  72. /** @type {!EventTarget} */ (this.tx_), 'error', this.dispatchError_);
  73. };
  74. goog.inherits(goog.db.Transaction, goog.events.EventTarget);
  75. /**
  76. * Dispatches an error event based on the given event, wrapping the error
  77. * if necessary.
  78. *
  79. * @param {Event} ev The error event given to the underlying IDBTransaction.
  80. * @private
  81. */
  82. goog.db.Transaction.prototype.dispatchError_ = function(ev) {
  83. if (ev.target instanceof goog.db.Error) {
  84. this.dispatchEvent(
  85. {type: goog.db.Transaction.EventTypes.ERROR, target: ev.target});
  86. } else {
  87. this.dispatchEvent({
  88. type: goog.db.Transaction.EventTypes.ERROR,
  89. target: goog.db.Error.fromRequest(
  90. /** @type {!IDBRequest} */ (ev.target), 'in transaction')
  91. });
  92. }
  93. };
  94. /**
  95. * Event types the Transaction can dispatch. COMPLETE events are dispatched
  96. * when the transaction is committed. If a transaction is aborted it dispatches
  97. * both an ABORT event and an ERROR event with the ABORT_ERR code. Error events
  98. * are dispatched on any error.
  99. *
  100. * @enum {string}
  101. */
  102. goog.db.Transaction.EventTypes = {
  103. COMPLETE: 'complete',
  104. ABORT: 'abort',
  105. ERROR: 'error'
  106. };
  107. /**
  108. * @return {goog.db.Transaction.TransactionMode} The transaction's mode.
  109. */
  110. goog.db.Transaction.prototype.getMode = function() {
  111. return /** @type {goog.db.Transaction.TransactionMode} */ (this.tx_.mode);
  112. };
  113. /**
  114. * @return {!goog.db.IndexedDb} The database that this transaction modifies.
  115. */
  116. goog.db.Transaction.prototype.getDatabase = function() {
  117. return this.db_;
  118. };
  119. /**
  120. * Opens an object store to do operations on in this transaction. The requested
  121. * object store must be one that is in this transaction's scope.
  122. * @see goog.db.IndexedDb#createTransaction
  123. *
  124. * @param {string} name The name of the requested object store.
  125. * @return {!goog.db.ObjectStore} The wrapped object store.
  126. * @throws {goog.db.Error} In case of error getting the object store.
  127. */
  128. goog.db.Transaction.prototype.objectStore = function(name) {
  129. try {
  130. return new goog.db.ObjectStore(this.tx_.objectStore(name));
  131. } catch (ex) {
  132. throw goog.db.Error.fromException(ex, 'getting object store ' + name);
  133. }
  134. };
  135. /**
  136. * @return {!goog.async.Deferred} A deferred that will fire once the
  137. * transaction is complete. It fires the errback chain if an error occurs
  138. * in the transaction, or if it is aborted.
  139. */
  140. goog.db.Transaction.prototype.wait = function() {
  141. var d = new goog.async.Deferred();
  142. goog.events.listenOnce(
  143. this, goog.db.Transaction.EventTypes.COMPLETE, goog.bind(d.callback, d));
  144. var errorKey;
  145. var abortKey = goog.events.listenOnce(
  146. this, goog.db.Transaction.EventTypes.ABORT, function() {
  147. goog.events.unlistenByKey(errorKey);
  148. d.errback(
  149. new goog.db.Error(
  150. goog.db.Error.ErrorCode.ABORT_ERR,
  151. 'waiting for transaction to complete'));
  152. });
  153. errorKey = goog.events.listenOnce(
  154. this, goog.db.Transaction.EventTypes.ERROR, function(e) {
  155. goog.events.unlistenByKey(abortKey);
  156. d.errback(e.target);
  157. });
  158. var db = this.getDatabase();
  159. return d.addCallback(function() { return db; });
  160. };
  161. /**
  162. * Aborts this transaction. No pending operations will be applied to the
  163. * database. Dispatches an ABORT event.
  164. */
  165. goog.db.Transaction.prototype.abort = function() {
  166. this.tx_.abort();
  167. };
  168. /** @override */
  169. goog.db.Transaction.prototype.disposeInternal = function() {
  170. goog.db.Transaction.base(this, 'disposeInternal');
  171. this.eventHandler_.dispose();
  172. };
  173. /**
  174. * The three possible transaction modes.
  175. * @see http://www.w3.org/TR/IndexedDB/#idl-def-IDBTransaction
  176. *
  177. * @enum {string}
  178. */
  179. goog.db.Transaction.TransactionMode = {
  180. READ_ONLY: 'readonly',
  181. READ_WRITE: 'readwrite',
  182. VERSION_CHANGE: 'versionchange'
  183. };