valor validar validacion una sincronas retornar pasar parametros otra funciones funcion formularios formulario ejemplos desde dentro con javascript function recursion callback

validar - Función de Javascript para manejar múltiples devoluciones de llamada desconocidas



validacion de formularios con javascript ejemplos (3)

Tengo un escenario en el que me gustaría enviar 2 o más funciones (como parámetros) en una función de controlador, y hacer que esa función de controlador ejecute cada función pasada como función de devolución de llamada para la función anterior.

Aquí hay un concepto general de la función que estoy tratando de escribir:

function functionChain() { // MAKE SURE WE HAVE AT LEAST 1 PARAMETER if ( arguments.length < 1 ) { return; } // for each parameter, call it (as a function) for ( var i=0; i<arguments.length; i++) { if ( typeof arguments[i] === ''function'' ) { call arguments[i]; } } } // example functionChain( function1, function2, function3 );

... así que en el código anterior, cada función se llamará en sucesión.

Donde me estoy atascado es cómo tratar cada llamada como una devolución de llamada cuando se completa la función anterior.

La forma en que abordaría esto es tener una variable (por simplicidad, digamos una variable global llamada functionChainComplete), y esperar a lanzar la siguiente función, y por supuesto, cada función que llamo establecería functionChainComplete en verdadero. Entonces, algo como esto:

// set global var for tracking var functionChainComplete; function functionChain() { // MAKE SURE WE HAVE AT LEAST 1 PARAMETER if ( arguments.length < 1 ) { return; } // SET GLOBAL VAR TO FALSE functionChainComplete = true; // for each parameter, call it (as a function) for ( var i=0; i<arguments.length; i++) { if ( typeof arguments[i] === ''function'' ) { if ( functionChainComplete == true ) { // call the next function and wait for true again functionChainComplete = false; call arguments[i]; } else { // try again in 50 ms (maybe setTimeout)? } } } } function1() { // do something, and when done, reset functionChainComplete functionChainComplete = true; } function2() { // do something, and when done, reset functionChainComplete functionChainComplete = true; } function3() { // do something, and when done, reset functionChainComplete functionChainComplete = true; } // example functionChain( function1, function2, function3 );

Como puede ver, el código anterior no aborda la pieza de devolución de llamada, y no estoy seguro de dónde tomarlo desde aquí. ¿Sospecho que se trata de una función recursiva? Estoy atascado.


¿Algo como esto? (Ver comentarios, pero bastante claro)

function functionChain() { var args = arguments; // MAKE SURE WE HAVE AT LEAST 1 PARAMETER if ( args.length < 1 ) { return; } // Start the process var i = -1; go(); function go() { // Pre-increment so we start at 0 ++i; if (i < args.length) { // We have a next function, do it and continue when we get the callback args[i](go); } } }

Ejemplo:

function functionChain() { var args = arguments; // MAKE SURE WE HAVE AT LEAST 1 PARAMETER if ( args.length < 1 ) { return; } // Start the process var i = -1; go(); function go() { // Pre-increment so we start at 0 ++i; if (i < args.length) { // We have a next function, do it and continue when we get the callback args[i](go); } } } // Just some functions for an example: function a(callback) { console.log("a"); callback(); } function b(callback) { console.log("b"); callback(); } // Note this one is async function c(callback) { setTimeout(function() { console.log("c"); callback(); }, 100); } function d(callback) { console.log("d"); callback(); } functionChain(a, b, c, d);

Dicho eso, una de las razones para las promesas es permitir la composición de funciones posiblemente asíncronas. Si sus funciones devolvían promesas, usaríamos la frase reducida:

function functionChain() { // Assumes the functions return promises (or at least thenables) Array.prototype.reduce.call(arguments, function(p, f) { return p.then(f); }, Promise.resolve()); }

function functionChain() { Array.prototype.reduce.call(arguments, function(p, f) { return p.then(f); }, Promise.resolve()); } // Just some functions for an example: function a(callback) { return new Promise(function(resolve) { console.log("a"); resolve(); }); } function b(callback) { return new Promise(function(resolve) { console.log("b"); resolve(); }); } // Note this one has a delay function c(callback) { return new Promise(function(resolve) { setTimeout(function() { console.log("c"); resolve(); }, 100); }); } function d(callback) { return new Promise(function(resolve) { console.log("d"); resolve(); }); } functionChain(a, b, c, d);


Esto podría hacerse con nsynjs :

  1. Ajustar todas las funciones lentas con devoluciones de llamada en envoltorios con nsynjs-aware (ver wait ()),
  2. Ponga su lógica en funcionamiento como si fuera síncrona (vea synchronousCode ()),
  3. Ejecute esa función a través del motor nsynjs (vea nsynjs.run ())

<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script> <script> var wait = function (ctx, ms) { setTimeout(function () { console.log(''firing timeout''); ctx.resume(); }, ms); }; wait.nsynjsHasCallback = true; function synchronousCode() { function function1() { console.log(''in function1''); wait(nsynjsCtx,1000); }; function function2() { console.log(''in function2''); wait(nsynjsCtx,1000); }; function function3() { console.log(''in function3''); wait(nsynjsCtx,1000); }; function functionChain() { // MAKE SURE WE HAVE AT LEAST 1 PARAMETER if ( arguments.length < 1 ) return; for ( var i=0; i<arguments.length; i++) { //console.log(i,arguments[i]); if ( typeof arguments[i] === ''function'' ) { arguments[i](); }; }; }; functionChain(function1,function2,function3); } nsynjs.run(synchronousCode,{},function(){ console.log("Synchronous Code done"); }) </script>

Consulte https://github.com/amaksr/nsynjs/tree/master/examples para obtener más ejemplos.


Supongamos que tiene alguna función, double , que toma un argumento, x y una devolución de llamada, k

const double = (x, k) => k(x * 2) double(2, console.log) // 4 double(3, console.log) // 6

Ahora digamos que queremos ejecutarlo 3 veces seguidas

const double = (x, k) => k(x * 2) const tripleDouble = (x, k) => double(x, y => double(y, z => double(z, k))) tripleDouble(2, console.log) // 16 tripleDouble(3, console.log) // 24

Pero, por supuesto, tuvimos que codificar estáticamente cada continuación ( y => ... z => ... ). ¿Cómo haríamos que esto funcione con una cantidad variable (conjunto) de funciones?

const double = (x, k) => k(x * 2) const composek = (...fs) => (x, k) => fs.reduce((acc, f) => k => acc(x => f(x, k)), k => k(x)) (k) const foo = composek(double, double, double) foo(2, console.log) // 16 foo(3, console.log) // 24

Esto está maduro para algo de abstracción, y presenta mi mónada favorita, la Mónada de Continuación.

const Cont = f => ({ runCont: f, chain: g => Cont(k => f(x => g(x).runCont(k))) }) Cont.of = x => Cont(k => k(x)) const composek = (...fs) => (x, k) => fs.reduce((acc,f) => acc.chain(x => Cont(k => f(x,k))), Cont.of(x)).runCont(k) const double = (x, k) => k(x * 2) const foo = composek(double, double, double) foo(2, console.log) // 16 foo(3, console.log) // 24

Si tiene libertad para cambiar las funciones que está encadenando, esto se limpia un poco más: aquí, el double tiene 1 parámetro y devuelve un Cont lugar de tomar una devolución de llamada como segundo argumento

const Cont = f => ({ runCont: f, chain: g => Cont(k => f(x => g(x).runCont(k))) }) Cont.of = x => Cont(k => k(x)) // simplified const composek = (...fs) => (x, k) => fs.reduce((acc,f) => acc.chain(f), Cont.of(x)).runCont(k) // simplified const double = x => Cont.of(x * 2) const foo = composek(double, double, double) foo(2, console.log) // 16 foo(3, console.log) // 24

Por supuesto, si el double fuera realmente asincrónico, funcionaría igual

// change double to be async; output stays the same const double = x => Cont(k => setTimeout(k, 1000, x * 2)) const foo = composek(double, double, double) foo(2, console.log) // 16 foo(3, console.log) // 24