X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/data/Batch.js diff --git a/src/data/Batch.js b/src/data/Batch.js new file mode 100644 index 00000000..51971b55 --- /dev/null +++ b/src/data/Batch.js @@ -0,0 +1,185 @@ +/** + * @author Ed Spencer + * @class Ext.data.Batch + * + *

Provides a mechanism to run one or more {@link Ext.data.Operation operations} in a given order. Fires the 'operationcomplete' event + * after the completion of each Operation, and the 'complete' event when all Operations have been successfully executed. Fires an 'exception' + * event if any of the Operations encounter an exception.

+ * + *

Usually these are only used internally by {@link Ext.data.proxy.Proxy} classes

+ * + * @constructor + * @param {Object} config Optional config object + */ +Ext.define('Ext.data.Batch', { + mixins: { + observable: 'Ext.util.Observable' + }, + + /** + * True to immediately start processing the batch as soon as it is constructed (defaults to false) + * @property autoStart + * @type Boolean + */ + autoStart: false, + + /** + * The index of the current operation being executed + * @property current + * @type Number + */ + current: -1, + + /** + * The total number of operations in this batch. Read only + * @property total + * @type Number + */ + total: 0, + + /** + * True if the batch is currently running + * @property isRunning + * @type Boolean + */ + isRunning: false, + + /** + * True if this batch has been executed completely + * @property isComplete + * @type Boolean + */ + isComplete: false, + + /** + * True if this batch has encountered an exception. This is cleared at the start of each operation + * @property hasException + * @type Boolean + */ + hasException: false, + + /** + * True to automatically pause the execution of the batch if any operation encounters an exception (defaults to true) + * @property pauseOnException + * @type Boolean + */ + pauseOnException: true, + + constructor: function(config) { + var me = this; + + me.addEvents( + /** + * @event complete + * Fired when all operations of this batch have been completed + * @param {Ext.data.Batch} batch The batch object + * @param {Object} operation The last operation that was executed + */ + 'complete', + + /** + * @event exception + * Fired when a operation encountered an exception + * @param {Ext.data.Batch} batch The batch object + * @param {Object} operation The operation that encountered the exception + */ + 'exception', + + /** + * @event operationcomplete + * Fired when each operation of the batch completes + * @param {Ext.data.Batch} batch The batch object + * @param {Object} operation The operation that just completed + */ + 'operationcomplete' + ); + + me.mixins.observable.constructor.call(me, config); + + /** + * Ordered array of operations that will be executed by this batch + * @property operations + * @type Array + */ + me.operations = []; + }, + + /** + * Adds a new operation to this batch + * @param {Object} operation The {@link Ext.data.Operation Operation} object + */ + add: function(operation) { + this.total++; + + operation.setBatch(this); + + this.operations.push(operation); + }, + + /** + * Kicks off the execution of the batch, continuing from the next operation if the previous + * operation encountered an exception, or if execution was paused + */ + start: function() { + this.hasException = false; + this.isRunning = true; + + this.runNextOperation(); + }, + + /** + * @private + * Runs the next operation, relative to this.current. + */ + runNextOperation: function() { + this.runOperation(this.current + 1); + }, + + /** + * Pauses execution of the batch, but does not cancel the current operation + */ + pause: function() { + this.isRunning = false; + }, + + /** + * Executes a operation by its numeric index + * @param {Number} index The operation index to run + */ + runOperation: function(index) { + var me = this, + operations = me.operations, + operation = operations[index], + onProxyReturn; + + if (operation === undefined) { + me.isRunning = false; + me.isComplete = true; + me.fireEvent('complete', me, operations[operations.length - 1]); + } else { + me.current = index; + + onProxyReturn = function(operation) { + var hasException = operation.hasException(); + + if (hasException) { + me.hasException = true; + me.fireEvent('exception', me, operation); + } else { + me.fireEvent('operationcomplete', me, operation); + } + + if (hasException && me.pauseOnException) { + me.pause(); + } else { + operation.setCompleted(); + me.runNextOperation(); + } + }; + + operation.setStarted(); + + me.proxy[operation.action](operation, onProxyReturn, me); + } + } +}); \ No newline at end of file