Batch.html 9.85 KB
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='Ext-data-Batch'>/**
</span> * @author Ed Spencer
 * @class Ext.data.Batch
 *
 * &lt;p&gt;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.&lt;/p&gt;
 *
 * &lt;p&gt;Usually these are only used internally by {@link Ext.data.proxy.Proxy} classes&lt;/p&gt;
 *
 */
Ext.define('Ext.data.Batch', {
    mixins: {
        observable: 'Ext.util.Observable'
    },

<span id='Ext-data-Batch-cfg-autoStart'>    /**
</span>     * @cfg {Boolean} autoStart
     * True to immediately start processing the batch as soon as it is constructed (defaults to false)
     */
    autoStart: false,
    
<span id='Ext-data-Batch-cfg-pauseOnException'>    /**
</span>     * @cfg {Boolean} pauseOnException
     * True to pause the execution of the batch if any operation encounters an exception
     * (defaults to false). If you set this to true you are responsible for implementing the appropriate
     * handling logic and restarting or discarding the batch as needed. There are different ways you could 
     * do this, e.g. by handling the batch's {@link #exception} event directly, or perhaps by overriding
     * {@link Ext.data.AbstractStore#onBatchException onBatchException} at the store level. If you do pause
     * and attempt to handle the exception you can call {@link #retry} to process the same operation again. 
     * 
     * Note that {@link Ext.data.Operation operations} are atomic, so any operations that may have succeeded
     * prior to an exception (and up until pausing the batch) will be finalized at the server level and will
     * not be automatically reversible. Any transactional / rollback behavior that might be desired would have
     * to be implemented at the application level. Pausing on exception will likely be most beneficial when
     * used in coordination with such a scheme, where an exception might actually affect subsequent operations
     * in the same batch and so should be handled before continuing with the next operation.
     * 
     * If you have not implemented transactional operation handling then this option should typically be left 
     * to the default of false (e.g. process as many operations as possible, and handle any exceptions 
     * asynchronously without holding up the rest of the batch).
     */
    pauseOnException: false,

<span id='Ext-data-Batch-property-current'>    /**
</span>     * @property {Number} current
     * The index of the current operation being executed. Read only
     */
    current: -1,

<span id='Ext-data-Batch-property-total'>    /**
</span>     * @property {Number} total
     * The total number of operations in this batch. Read only
     */
    total: 0,

<span id='Ext-data-Batch-property-isRunning'>    /**
</span>     * @property {Boolean} isRunning
     * True if the batch is currently running. Read only
     */
    isRunning: false,

<span id='Ext-data-Batch-property-isComplete'>    /**
</span>     * @property {Boolean} isComplete
     * True if this batch has been executed completely. Read only
     */
    isComplete: false,

<span id='Ext-data-Batch-property-hasException'>    /**
</span>     * @property {Boolean} hasException
     * True if this batch has encountered an exception. This is cleared at the start of each operation. Read only
     */
    hasException: false,

<span id='Ext-data-Batch-method-constructor'>    /**
</span>     * Creates new Batch object.
     * @param {Object} [config] Config object
     */
    constructor: function(config) {
        var me = this;

<span id='Ext-data-Batch-event-complete'>        /**
</span>         * @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
         */

<span id='Ext-data-Batch-event-exception'>        /**
</span>         * @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
         */

<span id='Ext-data-Batch-event-operationcomplete'>        /**
</span>         * @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
         */

        me.mixins.observable.constructor.call(me, config);

<span id='Ext-data-Batch-property-operations'>        /**
</span>         * Ordered array of operations that will be executed by this batch
         * @property {Ext.data.Operation[]} operations
         */
        me.operations = [];
        
<span id='Ext-data-Batch-property-exceptions'>        /**
</span>         * Ordered array of operations that raised an exception during the most recent
         * batch execution and did not successfully complete
         * @property {Ext.data.Operation[]} exceptions
         */
        me.exceptions = [];
    },

<span id='Ext-data-Batch-method-add'>    /**
</span>     * Adds a new operation to this batch at the end of the {@link #operations} array
     * @param {Object} operation The {@link Ext.data.Operation Operation} object
     * @return {Ext.data.Batch} this
     */
    add: function(operation) {
        this.total++;

        operation.setBatch(this);

        this.operations.push(operation);
        
        return this;
    },

<span id='Ext-data-Batch-method-start'>    /**
</span>     * Kicks off execution of the batch, continuing from the next operation if the previous
     * operation encountered an exception, or if execution was paused. Use this method to start
     * the batch for the first time or to restart a paused batch by skipping the current
     * unsuccessful operation.
     * 
     * To retry processing the current operation before continuing to the rest of the batch (e.g.
     * because you explicitly handled the operation's exception), call {@link #retry} instead.
     * 
     * Note that if the batch is already running any call to start will be ignored.
     * 
     * @return {Ext.data.Batch} this
     */
    start: function(/* private */ index) {
        var me = this;
        
        if (me.isRunning) {
            return me;
        }
        
        me.exceptions.length = 0;
        me.hasException = false;
        me.isRunning = true;

        return me.runOperation(Ext.isDefined(index) ? index : me.current + 1);
    },
    
<span id='Ext-data-Batch-method-retry'>    /**
</span>     * Kicks off execution of the batch, continuing from the current operation. This is intended
     * for restarting a {@link #pause paused} batch after an exception, and the operation that raised
     * the exception will now be retried. The batch will then continue with its normal processing until
     * all operations are complete or another exception is encountered.
     * 
     * Note that if the batch is already running any call to retry will be ignored.
     * 
     * @return {Ext.data.Batch} this
     */
    retry: function() {
        return this.start(this.current);
    },

<span id='Ext-data-Batch-method-runNextOperation'>    /**
</span>     * @private
     * Runs the next operation, relative to this.current.
     * @return {Ext.data.Batch} this
     */
    runNextOperation: function() {
        return this.runOperation(this.current + 1);
    },

<span id='Ext-data-Batch-method-pause'>    /**
</span>     * Pauses execution of the batch, but does not cancel the current operation
     * @return {Ext.data.Batch} this
     */
    pause: function() {
        this.isRunning = false;
        return this;
    },

<span id='Ext-data-Batch-method-runOperation'>    /**
</span>     * Executes an operation by its numeric index in the {@link #operations} array
     * @param {Number} index The operation index to run
     * @return {Ext.data.Batch} this
     */
    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.exceptions.push(operation);
                    me.fireEvent('exception', me, operation);
                }

                if (hasException &amp;&amp; me.pauseOnException) {
                    me.pause();
                } else {
                    operation.setCompleted();
                    me.fireEvent('operationcomplete', me, operation);
                    me.runNextOperation();
                }
            };

            operation.setStarted();

            me.proxy[operation.action](operation, onProxyReturn, me);
        }
        
        return me;
    }
});
</pre>
</body>
</html>