Source: lib/offline/indexeddb/db_operation.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.offline.indexeddb.DBOperation');
  7. goog.require('shaka.util.PublicPromise');
  8. /**
  9. * A DBOperation wraps an IndexedDB transaction in a promise.
  10. */
  11. shaka.offline.indexeddb.DBOperation = class {
  12. /**
  13. * @param {IDBTransaction} transaction
  14. * @param {string} storeName
  15. */
  16. constructor(transaction, storeName) {
  17. /** @private {IDBTransaction} */
  18. this.transaction_ = transaction;
  19. /** @private {IDBObjectStore} */
  20. this.store_ = transaction.objectStore(storeName);
  21. /** @private {!shaka.util.PublicPromise} */
  22. this.promise_ = new shaka.util.PublicPromise();
  23. // Connect the transaction and the promise together.
  24. // |event.preventDefault()| is used on all non-successful callbacks to
  25. // prevent Firefox from surfacing the error on the main thread.
  26. transaction.onabort = (event) => {
  27. event.preventDefault();
  28. this.promise_.reject();
  29. };
  30. transaction.onerror = (event) => {
  31. event.preventDefault();
  32. this.promise_.reject();
  33. };
  34. transaction.oncomplete = (event) => {
  35. this.promise_.resolve();
  36. };
  37. }
  38. /**
  39. * @return {!Promise}
  40. */
  41. async abort() {
  42. try {
  43. this.transaction_.abort();
  44. } catch (e) {
  45. // Ignore any exceptions that may be thrown as a result of aborting
  46. // the transaction.
  47. }
  48. try {
  49. // Wait for the promise to be rejected, but ignore the rejection error.
  50. await this.promise_;
  51. } catch (e) {}
  52. }
  53. /**
  54. * Calls the given callback for each entry in the database.
  55. *
  56. * @param {function(!IDBKeyType, T, !IDBCursorWithValue=):
  57. * (Promise|undefined)} callback
  58. * @return {!Promise}
  59. * @template T
  60. */
  61. forEachEntry(callback) {
  62. return new Promise((resolve, reject) => {
  63. const req = this.store_.openCursor();
  64. req.onerror = reject;
  65. req.onsuccess = async (event) => {
  66. // When we reach the end of the data that the cursor is iterating over,
  67. // |req.result| will be null to signal the end of the iteration.
  68. // https://developer.mozilla.org/en-US/docs/Web/API/IDBCursor/continue
  69. if (req.result == null) {
  70. resolve();
  71. return;
  72. }
  73. /** @type {!IDBCursorWithValue} */
  74. const cursor = req.result;
  75. await callback(cursor.key, cursor.value, cursor);
  76. cursor.continue();
  77. };
  78. });
  79. }
  80. /**
  81. * Get the store that the operation can interact with. Requests can be made
  82. * on the store. All requests made on the store will complete successfully
  83. * before the operation's promise will resolve. If any request fails, the
  84. * operation's promise will be rejected.
  85. *
  86. * @return {IDBObjectStore}
  87. */
  88. store() { return this.store_; }
  89. /**
  90. * Get the promise that wraps the transaction. This promise will resolve when
  91. * all requests on the object store complete successfully and the transaction
  92. * completes. If any request fails or the operation is aborted, the promise
  93. * will be rejected.
  94. *
  95. * @return {!Promise}
  96. */
  97. promise() { return this.promise_; }
  98. };