1 // Copyright (c) 2012 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 * @class FunctionSequence to invoke steps in sequence 9 * 10 * @param {string} name // TODO(JSDOC). 11 * @param {Array.<function>} steps Array of functions to invoke in parallel. 12 * @param {Object} logger // TODO(JSDOC). 13 * @param {function()} callback Callback to invoke on success. 14 * @param {function(string)} failureCallback Callback to invoke on failure. 15 * @constructor 16 */ 17 function FunctionParallel(name, steps, logger, callback, failureCallback) { 18 // Private variables hidden in closure 19 this.currentStepIdx_ = -1; 20 this.failed_ = false; 21 this.steps_ = steps; 22 this.callback_ = callback; 23 this.failureCallback_ = failureCallback; 24 this.logger = logger; 25 this.name = name; 26 27 this.remaining = this.steps_.length; 28 29 this.nextStep = this.nextStep_.bind(this); 30 this.onError = this.onError_.bind(this); 31 this.apply = this.start.bind(this); 32 } 33 34 35 /** 36 * Error handling function, which fires error callback. 37 * 38 * @param {string} err Error message. 39 * @private 40 */ 41 FunctionParallel.prototype.onError_ = function(err) { 42 if (!this.failed_) { 43 this.failed_ = true; 44 this.failureCallback_(err); 45 } 46 }; 47 48 /** 49 * Advances to next step. This method should not be used externally. In external 50 * cases should be used nextStep function, which is defined in closure and thus 51 * has access to internal variables of functionsequence. 52 * 53 * @private 54 */ 55 FunctionParallel.prototype.nextStep_ = function() { 56 if (--this.remaining == 0 && !this.failed_) { 57 this.callback_(); 58 } 59 }; 60 61 /** 62 * This function should be called only once on start, so start all the children 63 * at once 64 * @param {...} var_args // TODO(JSDOC). 65 */ 66 FunctionParallel.prototype.start = function(var_args) { 67 this.logger.vlog('Starting [' + this.steps_.length + '] parallel tasks ' + 68 'with ' + arguments.length + ' argument(s)'); 69 if (this.logger.verbose) { 70 for (var j = 0; j < arguments.length; j++) { 71 this.logger.vlog(arguments[j]); 72 } 73 } 74 for (var i = 0; i < this.steps_.length; i++) { 75 this.logger.vlog('Attempting to start step [' + this.steps_[i].name + ']'); 76 try { 77 this.steps_[i].apply(this, arguments); 78 } catch (e) { 79 this.onError(e.toString()); 80 } 81 } 82 }; 83