/ext-4.1.0_b3/src/data/Batch.js

https://bitbucket.org/srogerf/javascript · JavaScript · 236 lines · 75 code · 33 blank · 128 comment · 7 complexity · 34ad13571010d8b6a303e8e6e266f245 MD5 · raw file

  1. /**
  2. * @author Ed Spencer
  3. * @class Ext.data.Batch
  4. *
  5. * <p>Provides a mechanism to run one or more {@link Ext.data.Operation operations} in a given order. Fires the 'operationcomplete' event
  6. * after the completion of each Operation, and the 'complete' event when all Operations have been successfully executed. Fires an 'exception'
  7. * event if any of the Operations encounter an exception.</p>
  8. *
  9. * <p>Usually these are only used internally by {@link Ext.data.proxy.Proxy} classes</p>
  10. *
  11. */
  12. Ext.define('Ext.data.Batch', {
  13. mixins: {
  14. observable: 'Ext.util.Observable'
  15. },
  16. /**
  17. * @cfg {Boolean} autoStart
  18. * True to immediately start processing the batch as soon as it is constructed (defaults to false)
  19. */
  20. autoStart: false,
  21. /**
  22. * @cfg {Boolean} pauseOnException
  23. * True to pause the execution of the batch if any operation encounters an exception
  24. * (defaults to false). If you set this to true you are responsible for implementing the appropriate
  25. * handling logic and restarting or discarding the batch as needed. There are different ways you could
  26. * do this, e.g. by handling the batch's {@link #exception} event directly, or perhaps by overriding
  27. * {@link Ext.data.AbstractStore#onBatchException onBatchException} at the store level. If you do pause
  28. * and attempt to handle the exception you can call {@link #retry} to process the same operation again.
  29. *
  30. * Note that {@link Ext.data.Operation operations} are atomic, so any operations that may have succeeded
  31. * prior to an exception (and up until pausing the batch) will be finalized at the server level and will
  32. * not be automatically reversible. Any transactional / rollback behavior that might be desired would have
  33. * to be implemented at the application level. Pausing on exception will likely be most beneficial when
  34. * used in coordination with such a scheme, where an exception might actually affect subsequent operations
  35. * in the same batch and so should be handled before continuing with the next operation.
  36. *
  37. * If you have not implemented transactional operation handling then this option should typically be left
  38. * to the default of false (e.g. process as many operations as possible, and handle any exceptions
  39. * asynchronously without holding up the rest of the batch).
  40. */
  41. pauseOnException: false,
  42. /**
  43. * @property {Number} current
  44. * The index of the current operation being executed. Read only
  45. */
  46. current: -1,
  47. /**
  48. * @property {Number} total
  49. * The total number of operations in this batch. Read only
  50. */
  51. total: 0,
  52. /**
  53. * @property {Boolean} isRunning
  54. * True if the batch is currently running. Read only
  55. */
  56. isRunning: false,
  57. /**
  58. * @property {Boolean} isComplete
  59. * True if this batch has been executed completely. Read only
  60. */
  61. isComplete: false,
  62. /**
  63. * @property {Boolean} hasException
  64. * True if this batch has encountered an exception. This is cleared at the start of each operation. Read only
  65. */
  66. hasException: false,
  67. /**
  68. * Creates new Batch object.
  69. * @param {Object} [config] Config object
  70. */
  71. constructor: function(config) {
  72. var me = this;
  73. /**
  74. * @event complete
  75. * Fired when all operations of this batch have been completed
  76. * @param {Ext.data.Batch} batch The batch object
  77. * @param {Object} operation The last operation that was executed
  78. */
  79. /**
  80. * @event exception
  81. * Fired when a operation encountered an exception
  82. * @param {Ext.data.Batch} batch The batch object
  83. * @param {Object} operation The operation that encountered the exception
  84. */
  85. /**
  86. * @event operationcomplete
  87. * Fired when each operation of the batch completes
  88. * @param {Ext.data.Batch} batch The batch object
  89. * @param {Object} operation The operation that just completed
  90. */
  91. me.mixins.observable.constructor.call(me, config);
  92. /**
  93. * Ordered array of operations that will be executed by this batch
  94. * @property {Ext.data.Operation[]} operations
  95. */
  96. me.operations = [];
  97. /**
  98. * Ordered array of operations that raised an exception during the most recent
  99. * batch execution and did not successfully complete
  100. * @property {Ext.data.Operation[]} exceptions
  101. */
  102. me.exceptions = [];
  103. },
  104. /**
  105. * Adds a new operation to this batch at the end of the {@link #operations} array
  106. * @param {Object} operation The {@link Ext.data.Operation Operation} object
  107. * @return {Ext.data.Batch} this
  108. */
  109. add: function(operation) {
  110. this.total++;
  111. operation.setBatch(this);
  112. this.operations.push(operation);
  113. return this;
  114. },
  115. /**
  116. * Kicks off execution of the batch, continuing from the next operation if the previous
  117. * operation encountered an exception, or if execution was paused. Use this method to start
  118. * the batch for the first time or to restart a paused batch by skipping the current
  119. * unsuccessful operation.
  120. *
  121. * To retry processing the current operation before continuing to the rest of the batch (e.g.
  122. * because you explicitly handled the operation's exception), call {@link #retry} instead.
  123. *
  124. * Note that if the batch is already running any call to start will be ignored.
  125. *
  126. * @return {Ext.data.Batch} this
  127. */
  128. start: function(/* private */ index) {
  129. var me = this;
  130. if (me.isRunning) {
  131. return me;
  132. }
  133. me.exceptions.length = 0;
  134. me.hasException = false;
  135. me.isRunning = true;
  136. return me.runOperation(Ext.isDefined(index) ? index : me.current + 1);
  137. },
  138. /**
  139. * Kicks off execution of the batch, continuing from the current operation. This is intended
  140. * for restarting a {@link #pause paused} batch after an exception, and the operation that raised
  141. * the exception will now be retried. The batch will then continue with its normal processing until
  142. * all operations are complete or another exception is encountered.
  143. *
  144. * Note that if the batch is already running any call to retry will be ignored.
  145. *
  146. * @return {Ext.data.Batch} this
  147. */
  148. retry: function() {
  149. return this.start(this.current);
  150. },
  151. /**
  152. * @private
  153. * Runs the next operation, relative to this.current.
  154. * @return {Ext.data.Batch} this
  155. */
  156. runNextOperation: function() {
  157. return this.runOperation(this.current + 1);
  158. },
  159. /**
  160. * Pauses execution of the batch, but does not cancel the current operation
  161. * @return {Ext.data.Batch} this
  162. */
  163. pause: function() {
  164. this.isRunning = false;
  165. return this;
  166. },
  167. /**
  168. * Executes an operation by its numeric index in the {@link #operations} array
  169. * @param {Number} index The operation index to run
  170. * @return {Ext.data.Batch} this
  171. */
  172. runOperation: function(index) {
  173. var me = this,
  174. operations = me.operations,
  175. operation = operations[index],
  176. onProxyReturn;
  177. if (operation === undefined) {
  178. me.isRunning = false;
  179. me.isComplete = true;
  180. me.fireEvent('complete', me, operations[operations.length - 1]);
  181. } else {
  182. me.current = index;
  183. onProxyReturn = function(operation) {
  184. var hasException = operation.hasException();
  185. if (hasException) {
  186. me.hasException = true;
  187. me.exceptions.push(operation);
  188. me.fireEvent('exception', me, operation);
  189. }
  190. if (hasException && me.pauseOnException) {
  191. me.pause();
  192. } else {
  193. operation.setCompleted();
  194. me.fireEvent('operationcomplete', me, operation);
  195. me.runNextOperation();
  196. }
  197. };
  198. operation.setStarted();
  199. me.proxy[operation.action](operation, onProxyReturn, me);
  200. }
  201. return me;
  202. }
  203. });