Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / data / Batch.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @author Ed Spencer
17  * @class Ext.data.Batch
18  *
19  * <p>Provides a mechanism to run one or more {@link Ext.data.Operation operations} in a given order. Fires the 'operationcomplete' event
20  * after the completion of each Operation, and the 'complete' event when all Operations have been successfully executed. Fires an 'exception'
21  * event if any of the Operations encounter an exception.</p>
22  *
23  * <p>Usually these are only used internally by {@link Ext.data.proxy.Proxy} classes</p>
24  *
25  */
26 Ext.define('Ext.data.Batch', {
27     mixins: {
28         observable: 'Ext.util.Observable'
29     },
30
31     /**
32      * @property {Boolean} autoStart
33      * True to immediately start processing the batch as soon as it is constructed.
34      */
35     autoStart: false,
36
37     /**
38      * @property {Number} current
39      * The index of the current operation being executed
40      */
41     current: -1,
42
43     /**
44      * @property {Number} total
45      * The total number of operations in this batch. Read only
46      */
47     total: 0,
48
49     /**
50      * @property {Boolean} isRunning
51      * True if the batch is currently running
52      */
53     isRunning: false,
54
55     /**
56      * @property {Boolean} isComplete
57      * True if this batch has been executed completely
58      */
59     isComplete: false,
60
61     /**
62      * @property {Boolean} hasException
63      * True if this batch has encountered an exception. This is cleared at the start of each operation
64      */
65     hasException: false,
66
67     /**
68      * @property {Boolean} pauseOnException
69      * True to automatically pause the execution of the batch if any operation encounters an exception
70      */
71     pauseOnException: true,
72
73     /**
74      * Creates new Batch object.
75      * @param {Object} [config] Config object
76      */
77     constructor: function(config) {
78         var me = this;
79
80         me.addEvents(
81           /**
82            * @event complete
83            * Fired when all operations of this batch have been completed
84            * @param {Ext.data.Batch} batch The batch object
85            * @param {Object} operation The last operation that was executed
86            */
87           'complete',
88
89           /**
90            * @event exception
91            * Fired when a operation encountered an exception
92            * @param {Ext.data.Batch} batch The batch object
93            * @param {Object} operation The operation that encountered the exception
94            */
95           'exception',
96
97           /**
98            * @event operationcomplete
99            * Fired when each operation of the batch completes
100            * @param {Ext.data.Batch} batch The batch object
101            * @param {Object} operation The operation that just completed
102            */
103           'operationcomplete'
104         );
105
106         me.mixins.observable.constructor.call(me, config);
107
108         /**
109          * Ordered array of operations that will be executed by this batch
110          * @property {Ext.data.Operation[]} operations
111          */
112         me.operations = [];
113     },
114
115     /**
116      * Adds a new operation to this batch
117      * @param {Object} operation The {@link Ext.data.Operation Operation} object
118      */
119     add: function(operation) {
120         this.total++;
121
122         operation.setBatch(this);
123
124         this.operations.push(operation);
125     },
126
127     /**
128      * Kicks off the execution of the batch, continuing from the next operation if the previous
129      * operation encountered an exception, or if execution was paused
130      */
131     start: function() {
132         this.hasException = false;
133         this.isRunning = true;
134
135         this.runNextOperation();
136     },
137
138     /**
139      * @private
140      * Runs the next operation, relative to this.current.
141      */
142     runNextOperation: function() {
143         this.runOperation(this.current + 1);
144     },
145
146     /**
147      * Pauses execution of the batch, but does not cancel the current operation
148      */
149     pause: function() {
150         this.isRunning = false;
151     },
152
153     /**
154      * Executes a operation by its numeric index
155      * @param {Number} index The operation index to run
156      */
157     runOperation: function(index) {
158         var me = this,
159             operations = me.operations,
160             operation  = operations[index],
161             onProxyReturn;
162
163         if (operation === undefined) {
164             me.isRunning  = false;
165             me.isComplete = true;
166             me.fireEvent('complete', me, operations[operations.length - 1]);
167         } else {
168             me.current = index;
169
170             onProxyReturn = function(operation) {
171                 var hasException = operation.hasException();
172
173                 if (hasException) {
174                     me.hasException = true;
175                     me.fireEvent('exception', me, operation);
176                 } else {
177                     me.fireEvent('operationcomplete', me, operation);
178                 }
179
180                 if (hasException && me.pauseOnException) {
181                     me.pause();
182                 } else {
183                     operation.setCompleted();
184                     me.runNextOperation();
185                 }
186             };
187
188             operation.setStarted();
189
190             me.proxy[operation.action](operation, onProxyReturn, me);
191         }
192     }
193 });