Upgrade to ExtJS 4.0.2 - Released 06/09/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      * True to immediately start processing the batch as soon as it is constructed (defaults to false)
33      * @property autoStart
34      * @type Boolean
35      */
36     autoStart: false,
37     
38     /**
39      * The index of the current operation being executed
40      * @property current
41      * @type Number
42      */
43     current: -1,
44     
45     /**
46      * The total number of operations in this batch. Read only
47      * @property total
48      * @type Number
49      */
50     total: 0,
51     
52     /**
53      * True if the batch is currently running
54      * @property isRunning
55      * @type Boolean
56      */
57     isRunning: false,
58     
59     /**
60      * True if this batch has been executed completely
61      * @property isComplete
62      * @type Boolean
63      */
64     isComplete: false,
65     
66     /**
67      * True if this batch has encountered an exception. This is cleared at the start of each operation
68      * @property hasException
69      * @type Boolean
70      */
71     hasException: false,
72     
73     /**
74      * True to automatically pause the execution of the batch if any operation encounters an exception (defaults to true)
75      * @property pauseOnException
76      * @type Boolean
77      */
78     pauseOnException: true,
79     
80     /**
81      * Creates new Batch object.
82      * @param {Object} config (optional) Config object
83      */
84     constructor: function(config) {   
85         var me = this;
86                      
87         me.addEvents(
88           /**
89            * @event complete
90            * Fired when all operations of this batch have been completed
91            * @param {Ext.data.Batch} batch The batch object
92            * @param {Object} operation The last operation that was executed
93            */
94           'complete',
95           
96           /**
97            * @event exception
98            * Fired when a operation encountered an exception
99            * @param {Ext.data.Batch} batch The batch object
100            * @param {Object} operation The operation that encountered the exception
101            */
102           'exception',
103           
104           /**
105            * @event operationcomplete
106            * Fired when each operation of the batch completes
107            * @param {Ext.data.Batch} batch The batch object
108            * @param {Object} operation The operation that just completed
109            */
110           'operationcomplete'
111         );
112         
113         me.mixins.observable.constructor.call(me, config);
114         
115         /**
116          * Ordered array of operations that will be executed by this batch
117          * @property operations
118          * @type Array
119          */
120         me.operations = [];
121     },
122     
123     /**
124      * Adds a new operation to this batch
125      * @param {Object} operation The {@link Ext.data.Operation Operation} object
126      */
127     add: function(operation) {
128         this.total++;
129         
130         operation.setBatch(this);
131         
132         this.operations.push(operation);
133     },
134     
135     /**
136      * Kicks off the execution of the batch, continuing from the next operation if the previous
137      * operation encountered an exception, or if execution was paused
138      */
139     start: function() {
140         this.hasException = false;
141         this.isRunning = true;
142         
143         this.runNextOperation();
144     },
145     
146     /**
147      * @private
148      * Runs the next operation, relative to this.current.
149      */
150     runNextOperation: function() {
151         this.runOperation(this.current + 1);
152     },
153     
154     /**
155      * Pauses execution of the batch, but does not cancel the current operation
156      */
157     pause: function() {
158         this.isRunning = false;
159     },
160     
161     /**
162      * Executes a operation by its numeric index
163      * @param {Number} index The operation index to run
164      */
165     runOperation: function(index) {
166         var me = this,
167             operations = me.operations,
168             operation  = operations[index],
169             onProxyReturn;
170         
171         if (operation === undefined) {
172             me.isRunning  = false;
173             me.isComplete = true;
174             me.fireEvent('complete', me, operations[operations.length - 1]);
175         } else {
176             me.current = index;
177             
178             onProxyReturn = function(operation) {
179                 var hasException = operation.hasException();
180                 
181                 if (hasException) {
182                     me.hasException = true;
183                     me.fireEvent('exception', me, operation);
184                 } else {
185                     me.fireEvent('operationcomplete', me, operation);
186                 }
187
188                 if (hasException && me.pauseOnException) {
189                     me.pause();
190                 } else {
191                     operation.setCompleted();
192                     me.runNextOperation();
193                 }
194             };
195             
196             operation.setStarted();
197             
198             me.proxy[operation.action](operation, onProxyReturn, me);
199         }
200     }
201 });