UNPKG

vox-core

Version:

Runtime de aplicaciones multiplataforma

450 lines (371 loc) 8.5 kB
var Util= core.VW.Util; /** * Clase que representa tareas asíncronas. Versión light compatible con Promise de EcmaScript * @memberof VW * @constructor */ var Task= module.exports= function(){ this.uid= Task.id++; this.$istask$$= true; } Task.id=0; /** * Esperar una determinada cantidad de segundos * @param {int} time * @return {void} */ Task.sleep= function(time){ var task= new Task() if(time<0){ setImmediate(function(){ task.finish() }) } else{ setTimeout(function(){ task.finish() }, time) } return task } /** * Convertir una función que recibe un callback a una tarea * @param {Function} func * @param {object} [target] Objeto al que se le aplica la función * @return {Task} Nueva tarea */ Task.fromFunctionWithCallback= function(func, self){ return function(){ var args= Array.prototype.slice.call(arguments, 0, arguments.length) var task = new Task() args.push(function(er, data){ if(er){ task.exception= er } else{ task.result= data||task.result } task.finish() }) task.result= func.apply(self||this, args) return task } } /** * Procesar el resultado de la tarea antes de exponer el resultado * @param {Function} before * @return {void} */ Task.prototype.beforeExpose=function(/*function*/before){ if(!this.before){ this.before=[]; } if(typeof before == "function"){ this.before.push(before); } } /** * Añadir un callback para ejecutar cuando la tarea finaliza correctamente * @param {Function} callback * @param {Function} [onerror] * @return {Task} this */ Task.prototype.then=function(callback, onerror){ this.p_oncomplete=callback; if(onerror){ this.catch(onerror); } if(!this.get_executing()){ this.finish(); } return this; } /** * Añadir un callback para ejecutar cuando la tarea finaliza con error * @param {Function} onerror * @return {Task} this */ Task.prototype.catch=function(callback){ this.p_onerror=callback; if(!this.get_executing()){ this.finish(); } return this; } /** * Crear una nueva tarea que finaliza cuando finalizan todas las tareas que se pasan como argumento, o cuando una tarea produce error * @param {Iterator<Task>} tasks * @return {Task} Nueva tarea creada */ Task.waitMany=function(/*Iterable*/tasks){ var iterator=tasks[Symbol.iterator](); var rtask= new core.VW.Task(),total=0; var totaldata=[],alltasks=[],faulted; while(true){ var step; if((step= iterator.next()).done){ break; } var task=step.value; total++; alltasks.push(task); (function(task){ task.oncomplete= function(){ if(faulted){ return; } if(task.exception){ rtask.exception=task.exception; faulted=true; for(var i=0;i<alltasks.length;i++){ try{ alltasks[i].cancel(); }catch(e){} } rtask.finish(); return; } totaldata.push(task.result); if(totaldata.length==total){ rtask.result=totaldata; rtask.finish(); return; } }; })(task); } return rtask; } Task.all= Task.waitMany Task.waitToCallback= function(/*Task*/task,/*function*/callback){ task.oncomplete= callback; } Task.prototype.waitToCallback= function(/*function*/callback){ this.oncomplete= callback; } Task.prototype.toString= Task.prototype.inspect= function(){ return "Task " + this.uid + ": " + JSON.stringify({ isCancelled: this.isCancelled, isCompleted: this.isCompleted, isFaulted: this.isFaulted }); } Task.get= function(args){ if(args[args.length-1]&& args[args.length-1].$istask$$){ var t= args[args.length-1]; t.inherited= true; return t; } else{ return new Task(); } eventEmitter.call(this); } /** * Cancelar la tarea si está pendiente. Produce la excepción {@link core.VW.TaskCancelledException}. * @return {void} */ Task.prototype.cancel= function(/* bool */force){ this.cancelled= true; this.$exception= new core.VW.TaskCancelledException("El usuario canceló"); } /** * Resultado de la tarea * @type {Mixed} */ Task.prototype.result=undefined Task.prototype.get_result= function(){ return this.$result; } Task.prototype.set_result= function(val){ if(this.cancelled){ return; } return this.$result=val; } Task.prototype.reset= function(/*bool */all){ this.$exception=null; this.$iscompleted= false; this.$isfaulted= false; this.$result= null; this.$oncomplete= null; this.$onerror=null; this.cancelled=false; if(all){ this.$alwaysonerror=null; } } Task.prototype.resetEvents= function(/*bool */all){ this.$oncomplete= null; this.$onerror=null; this.$alwaysonerror=null; } /** * Marcar como finalizada la tarea * return {void} */ Task.prototype.finish= function(result){ var self=this; if(arguments.length>0){ self.result= result; } if(this.before){ //if(!self.$exception){ var func= this.before.shift(); if(func){ var er,v if(func instanceof Task){ v=func } else{ try{ v=func(self.result); } catch(e){ self.exception= e; } } if(v instanceof Task){ v.oncomplete= function(){ self.result= v.result; self.$exception= v.exception; self.finish(); } return; } else{ if(v!==undefined) self.result= v self.finish(); } return; } //} } if(self.exception){ if(self.p_onerror){ self.p_onerror(self.exception); //self.reset(); return; } else if(self.$onerror){ var c= self.$onerror; c(self.exception); //self.reset(); return; } else if(self.$alwaysonerror){ self.$alwaysonerror(self.exception); //self.reset(); return; } } self.$iscompleted=true if(!self.exception && self.p_oncomplete){ self.p_oncomplete(self.result); //self.reset(); } if(self.$oncomplete){ var c= self.$oncomplete; c(self.result); //self.reset(); } } /** * Función a ejecutar al terminar la tarea * @type {Function} */ Task.prototype.oncomplete=undefined Task.prototype.get_oncomplete= function(){ return this.$oncomplete; } /** * Función a ejecutar cuando ocurre un erro en la ejecución de la tarea * @type {Function} */ Task.prototype.onerror=undefined Task.prototype.get_onerror= function(){ return this.$onerror; } Task.prototype.alwaysonerror=undefined Task.prototype.get_alwaysonerror= function(){ return this.$alwaysonerror; } Task.prototype.set_oncomplete= function(value){ this.$oncomplete=value; if(!this.get_executing()){ this.finish(); } return value; } Task.prototype.set_onerror= function(value){ this.$onerror=value if(!this.get_executing()){ this.finish(); } return value; } Task.prototype.set_alwaysonerror= function(value){ this.$alwaysonerror=value if(!this.get_executing()){ this.finish(); } return value; } /** * Indica si la tarea se ha completado * @type {Boolean} */ Task.prototype.isCompleted=undefined Task.prototype.get_isCompleted= function(){ return !!this.$iscompleted } /** * Indica si la tarea se está ejecutando * @type {Boolean} */ Task.prototype.executing= undefined Task.prototype.get_executing= function(){ return !(!!this.$iscompleted || !!this.$isfaulted || !!this.cancelled); } /** * Indica si la tarea terminó con errores * @type {Boolean} */ Task.prototype.isFaulted= undefined Task.prototype.get_isFaulted= function(){ return !!this.$isfaulted; } /** * Indica si la tarea fue cancelada * @type {Boolean} */ Task.prototype.isCancelled=undefined Task.prototype.get_isCancelled= function(){ return !!this.cancelled; } /** * Error ocurrido durante la ejecución de la tarea * @type {Error|System.Exception} */ Task.prototype.exception=undefined Task.prototype.get_exception= function(){ return this.$exception; } Task.prototype.set_exception= function(err){ if(!err){ return; } if(!(err instanceof Error)){ var ex= new core.System.Exception(err.message || err.toString(), err); if(typeof err =="object"){ for(var id in err){ ex[id]=err[id] } } err= ex } this.$isfaulted=true; return this.$exception= err; } Util.createProperties(Task,Task.prototype);