Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: chrome/browser/resources/file_manager/js/async_util.js

Issue 39123003: [Files.app] Split the JavaScript files into subdirectories: common, background, and foreground (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed test failure. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8 * Namespace for async utility functions.
9 */
10 var AsyncUtil = {};
11
12 /**
13 * Asynchronous version of Array.forEach.
14 * This executes a provided function callback once per array element, then
15 * run completionCallback to notify the completion.
16 * The callback can be an asynchronous function, but the execution is
17 * sequentially done.
18 *
19 * @param {Array.<T>} array The array to be iterated.
20 * @param {function(function(), T, number, Array.<T>} callback The iteration
21 * callback. The first argument is a callback to notify the completion of
22 * the iteration.
23 * @param {function()} completionCallback Called when all iterations are
24 * completed.
25 * @param {Object=} opt_thisObject Bound to callback if given.
26 * @template T
27 */
28 AsyncUtil.forEach = function(
29 array, callback, completionCallback, opt_thisObject) {
30 if (opt_thisObject)
31 callback = callback.bind(opt_thisObject);
32
33 var queue = new AsyncUtil.Queue();
34 for (var i = 0; i < array.length; i++) {
35 queue.run(function(element, index, iterationCompletionCallback) {
36 callback(iterationCompletionCallback, element, index, array);
37 }.bind(null, array[i], i));
38 }
39 queue.run(function(iterationCompletionCallback) {
40 completionCallback(); // Don't pass iteration completion callback.
41 });
42 };
43
44 /**
45 * Creates a class for executing several asynchronous closures in a fifo queue.
46 * Added tasks will be executed sequentially in order they were added.
47 *
48 * @constructor
49 */
50 AsyncUtil.Queue = function() {
51 this.running_ = false;
52 this.closures_ = [];
53 };
54
55 /**
56 * @return {boolean} True when a task is running, otherwise false.
57 */
58 AsyncUtil.Queue.prototype.isRunning = function() {
59 return this.running_;
60 };
61
62 /**
63 * Enqueues a closure to be executed.
64 * @param {function(function())} closure Closure with a completion callback to
65 * be executed.
66 */
67 AsyncUtil.Queue.prototype.run = function(closure) {
68 this.closures_.push(closure);
69 if (!this.running_)
70 this.continue_();
71 };
72
73 /**
74 * Serves the next closure from the queue.
75 * @private
76 */
77 AsyncUtil.Queue.prototype.continue_ = function() {
78 if (!this.closures_.length) {
79 this.running_ = false;
80 return;
81 }
82
83 // Run the next closure.
84 this.running_ = true;
85 var closure = this.closures_.shift();
86 closure(this.continue_.bind(this));
87 };
88
89 /**
90 * Cancels all pending tasks. Note that this does NOT cancel the task running
91 * currently.
92 */
93 AsyncUtil.Queue.prototype.cancel = function() {
94 this.closures_ = [];
95 };
96
97 /**
98 * Creates a class for executing several asynchronous closures in a group in
99 * a dependency order.
100 *
101 * @constructor
102 */
103 AsyncUtil.Group = function() {
104 this.addedTasks_ = {};
105 this.pendingTasks_ = {};
106 this.finishedTasks_ = {};
107 this.completionCallbacks_ = [];
108 };
109
110 /**
111 * Enqueues a closure to be executed after dependencies are completed.
112 *
113 * @param {function(function())} closure Closure with a completion callback to
114 * be executed.
115 * @param {Array.<string>=} opt_dependencies Array of dependencies. If no
116 * dependencies, then the the closure will be executed immediately.
117 * @param {string=} opt_name Task identifier. Specify to use in dependencies.
118 */
119 AsyncUtil.Group.prototype.add = function(closure, opt_dependencies, opt_name) {
120 var length = Object.keys(this.addedTasks_).length;
121 var name = opt_name || ('(unnamed#' + (length + 1) + ')');
122
123 var task = {
124 closure: closure,
125 dependencies: opt_dependencies || [],
126 name: name
127 };
128
129 this.addedTasks_[name] = task;
130 this.pendingTasks_[name] = task;
131 };
132
133 /**
134 * Runs the enqueued closured in order of dependencies.
135 *
136 * @param {function()=} opt_onCompletion Completion callback.
137 */
138 AsyncUtil.Group.prototype.run = function(opt_onCompletion) {
139 if (opt_onCompletion)
140 this.completionCallbacks_.push(opt_onCompletion);
141 this.continue_();
142 };
143
144 /**
145 * Runs enqueued pending tasks whose dependencies are completed.
146 * @private
147 */
148 AsyncUtil.Group.prototype.continue_ = function() {
149 // If all of the added tasks have finished, then call completion callbacks.
150 if (Object.keys(this.addedTasks_).length ==
151 Object.keys(this.finishedTasks_).length) {
152 for (var index = 0; index < this.completionCallbacks_.length; index++) {
153 var callback = this.completionCallbacks_[index];
154 callback();
155 }
156 this.completionCallbacks_ = [];
157 return;
158 }
159
160 for (var name in this.pendingTasks_) {
161 var task = this.pendingTasks_[name];
162 var dependencyMissing = false;
163 for (var index = 0; index < task.dependencies.length; index++) {
164 var dependency = task.dependencies[index];
165 // Check if the dependency has finished.
166 if (!this.finishedTasks_[dependency])
167 dependencyMissing = true;
168 }
169 // All dependences finished, therefore start the task.
170 if (!dependencyMissing) {
171 delete this.pendingTasks_[task.name];
172 task.closure(this.finish_.bind(this, task));
173 }
174 }
175 };
176
177 /**
178 * Finishes the passed task and continues executing enqueued closures.
179 *
180 * @param {Object} task Task object.
181 * @private
182 */
183 AsyncUtil.Group.prototype.finish_ = function(task) {
184 this.finishedTasks_[task.name] = task;
185 this.continue_();
186 };
187
188 /**
189 * Aggregates consecutive calls and executes the closure only once instead of
190 * several times. The first call is always called immediately, and the next
191 * consecutive ones are aggregated and the closure is called only once once
192 * |delay| amount of time passes after the last call to run().
193 *
194 * @param {function()} closure Closure to be aggregated.
195 * @param {number=} opt_delay Minimum aggregation time in milliseconds. Default
196 * is 50 milliseconds.
197 * @constructor
198 */
199 AsyncUtil.Aggregation = function(closure, opt_delay) {
200 /**
201 * @type {number}
202 * @private
203 */
204 this.delay_ = opt_delay || 50;
205
206 /**
207 * @type {function()}
208 * @private
209 */
210 this.closure_ = closure;
211
212 /**
213 * @type {number?}
214 * @private
215 */
216 this.scheduledRunsTimer_ = null;
217
218 /**
219 * @type {number}
220 * @private
221 */
222 this.lastRunTime_ = 0;
223 };
224
225 /**
226 * Runs a closure. Skips consecutive calls. The first call is called
227 * immediately.
228 */
229 AsyncUtil.Aggregation.prototype.run = function() {
230 // If recently called, then schedule the consecutive call with a delay.
231 if (Date.now() - this.lastRunTime_ < this.delay_) {
232 this.cancelScheduledRuns_();
233 this.scheduledRunsTimer_ = setTimeout(this.runImmediately_.bind(this),
234 this.delay_ + 1);
235 this.lastRunTime_ = Date.now();
236 return;
237 }
238
239 // Otherwise, run immediately.
240 this.runImmediately_();
241 };
242
243 /**
244 * Calls the schedule immediately and cancels any scheduled calls.
245 * @private
246 */
247 AsyncUtil.Aggregation.prototype.runImmediately_ = function() {
248 this.cancelScheduledRuns_();
249 this.closure_();
250 this.lastRunTime_ = Date.now();
251 };
252
253 /**
254 * Cancels all scheduled runs (if any).
255 * @private
256 */
257 AsyncUtil.Aggregation.prototype.cancelScheduledRuns_ = function() {
258 if (this.scheduledRunsTimer_) {
259 clearTimeout(this.scheduledRunsTimer_);
260 this.scheduledRunsTimer_ = null;
261 }
262 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/app_installer.js ('k') | chrome/browser/resources/file_manager/js/background.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698