validar validacion tipos pagina funciones funcion formularios formulario enviar ejemplos ejecutar con cargar carga asincrona antes javascript promise q

javascript - validacion - ¿Cómo devuelve correctamente los valores múltiples de una promesa?



validar formulario javascript html5 (8)

Así es como creo que deberías estar haciendo.

dividiendo la cadena

Debido a que ambas funciones usarán amazingData , tiene sentido tenerlas en una función dedicada. Normalmente hago eso cada vez que quiero reutilizar algunos datos, por lo que siempre está presente como una función arg.

Como su ejemplo ejecuta algún código, supongo que todo se declara dentro de una función. Lo llamaré toto () . Luego tendremos otra función que se ejecutará tanto afterSomething () como afterSomethingElse () .

function toto() { return somethingAsync() .then( tata ); }

También notará que agregué una declaración de devolución , ya que generalmente es el camino a seguir con Promesas: siempre devuelve una promesa para que podamos seguir encadenando si es necesario. Aquí, somethingAsync () producirá datos increíbles y estará disponible en todas partes dentro de la nueva función.

Ahora, ¿cómo se verá esta nueva función normalmente depende de si processAsync () también es asíncrono ?

processAsync no asíncrono

No hay razón para complicar demasiado las cosas si processAsync () no es asíncrono. Algún buen código secuencial lo haría.

function tata( amazingData ) { var processed = afterSomething( amazingData ); return afterSomethingElse( amazingData, processed ); } function afterSomething( amazingData ) { return processAsync( amazingData ); } function afterSomethingElse( amazingData, processedData ) { }

Tenga en cuenta que no importa si afterSomethingElse () está haciendo algo asíncrono o no. Si lo hace, se devolverá una promesa y la cadena puede continuar. Si no es así, se devolverá el valor del resultado. Pero debido a que la función se llama desde a continuación () , el valor se envolverá en una promesa de todos modos (al menos en Javascript sin procesar).

processAsync asíncrono

Si processAsync () es asíncrono, el código se verá ligeramente diferente. Aquí consideramos que afterSomething () y afterSomethingElse () no se reutilizarán en ningún otro lugar.

function tata( amazingData ) { return afterSomething() .then( afterSomethingElse ); function afterSomething( /* no args */ ) { return processAsync( amazingData ); } function afterSomethingElse( processedData ) { /* amazingData can be accessed here */ } }

Igual que antes para afterSomethingElse () . Puede ser asíncrono o no. Se devolverá una promesa o un valor envuelto en una promesa resuelta.

Su estilo de codificación es bastante parecido al que solía hacer, por eso respondí incluso después de 2 años. No soy un gran admirador de tener funciones anónimas en todas partes. Me resulta difícil de leer. Incluso si es bastante común en la comunidad. Es como reemplazamos el infierno de devolución de llamada por un purgatorio de promesas .

También me gusta mantener el nombre de las funciones en el corto. De todos modos, solo se definirán localmente. Y la mayoría de las veces llamarán a otra función definida en otro lugar, tan reutilizable, para hacer el trabajo. Incluso hago eso para funciones con solo 1 parámetro, por lo que no necesito que la función entre y salga cuando agrego / elimino un parámetro a la firma de la función.

Ejemplo de comer

Aquí hay un ejemplo:

function goingThroughTheEatingProcess(plenty, of, args, to, match, real, life) { return iAmAsync() .then(chew) .then(swallow); function chew(result) { return carefullyChewThis(plenty, of, args, "water", "piece of tooth", result); } function swallow(wine) { return nowIsTimeToSwallow(match, real, life, wine); } } function iAmAsync() { return Promise.resolve("mooooore"); } function carefullyChewThis(plenty, of, args, and, some, more) { return true; } function nowIsTimeToSwallow(match, real, life, bobool) { }

No se concentre demasiado en Promise.resolve () . Es solo una forma rápida de crear una promesa resuelta. Lo que trato de lograr con esto es tener todo el código que estoy ejecutando en una sola ubicación, justo debajo de los thens . Todas las demás funciones con un nombre más descriptivo son reutilizables.

El inconveniente de esta técnica es que está definiendo muchas funciones. Pero me temo que es un dolor necesario para evitar tener funciones anónimas por todas partes. ¿Y cuál es el riesgo de todos modos: un desbordamiento de pila? (¡broma!)

El uso de matrices u objetos como se define en otras respuestas también funcionaría. Esta de alguna manera es la respuesta propuesta por Kevin Reid .

También puede usar bind () o Promise.all () . Tenga en cuenta que aún requerirán que divida su código.

usando bind

Si desea mantener sus funciones reutilizables pero realmente no necesita mantener lo que está dentro de ese tiempo, puede usar bind () .

function tata( amazingData ) { return afterSomething( amazingData ) .then( afterSomethingElse.bind(null, amazingData) ); } function afterSomething( amazingData ) { return processAsync( amazingData ); } function afterSomethingElse( amazingData, processedData ) { }

Para mantenerlo simple, bind () antepondrá la lista de argumentos (excepto el primero) a la función cuando se llame.

usando Promise.all

En su publicación mencionó el uso de spread () . Nunca usé el marco que estás usando, pero así es como deberías poder usarlo.

Algunos creen que Promise.all () es la solución a todos los problemas, por lo que merece ser mencionado, supongo.

function tata( amazingData ) { return Promise.all( [ amazingData, afterSomething( amazingData ) ] ) .then( afterSomethingElse ); } function afterSomething( amazingData ) { return processAsync( amazingData ); } function afterSomethingElse( args ) { var amazingData = args[0]; var processedData = args[1]; }

Puede pasar datos a Promise.all () , tenga en cuenta la presencia de la matriz, siempre y cuando las promesas, pero asegúrese de que ninguna de las promesas falle, de lo contrario se detendrá el procesamiento.

Y en lugar de definir nuevas variables a partir del argumento args , debería poder usar spread () en lugar de then () para todo tipo de trabajo increíble.

Recientemente me he encontrado con una cierta situación un par de veces, que no sabía cómo resolver adecuadamente. Asuma el siguiente código:

somethingAsync() .then( afterSomething ) .then( afterSomethingElse ) function afterSomething( amazingData ) { return processAsync( amazingData ); } function afterSomethingElse( processedData ) { }

Ahora puede surgir una situación en la que me gustaría tener acceso a datos amazingData en afterSomethingElse .

Una solución obvia sería devolver una matriz o un hash de afterSomething , porque, bueno, solo puede devolver un valor de una función. Pero me pregunto si hay forma de que afterSomethingElse acepte 2 parámetros e invoque de la misma manera, ya que parece mucho más fácil de documentar y comprender.

Solo me pregunto acerca de esta posibilidad, ya que hay Q.spread , que hace algo similar a lo que quiero.


Dos cosas que puedes hacer, devolver un objeto

somethingAsync() .then( afterSomething ) .then( afterSomethingElse ); function processAsync (amazingData) { //processSomething return { amazingData: amazingData, processedData: processedData }; } function afterSomething( amazingData ) { return processAsync( amazingData ); } function afterSomethingElse( dataObj ) { let amazingData = dataObj.amazingData, processedData = dataObj.proccessedData; }

Use el alcance!

var amazingData; somethingAsync() .then( afterSomething ) .then( afterSomethingElse ) function afterSomething( returnedAmazingData ) { amazingData = returnedAmazingData; return processAsync( amazingData ); } function afterSomethingElse( processedData ) { //use amazingData here }


Lo que devuelva de una promesa se envolverá en una promesa que se .then() en la siguiente etapa .then() .

Se vuelve interesante cuando necesita devolver una o más promesas junto con uno o más valores sincrónicos como;

Promise.resolve([Promise.resolve(1), Promise.resolve(2), 3, 4]) .then(([p1,p2,n1,n2]) => /* p1 and p2 are still promises */);

En estos casos, sería esencial usar Promise.all() para obtener las promesas p1 y p2 sin envolver en la siguiente etapa .then() como

Promise.resolve(Promise.all([Promise.resolve(1), Promise.resolve(2), 3, 4])) .then(([p1,p2,n1,n2]) => /* p1 is 1, p2 is 2, n1 is 3 and n2 is 4 */);


Puede devolver un objeto que contenga ambos valores; no hay nada de malo en eso.

Otra estrategia es mantener el valor, a través de cierres, en lugar de pasarlo:

somethingAsync().then(afterSomething); function afterSomething(amazingData) { return processAsync(amazingData).then(function (processedData) { // both amazingData and processedData are in scope here }); }

Forma totalmente en lugar de parcialmente en línea (equivalente, posiblemente más consistente):

somethingAsync().then(function (amazingData) { return processAsync(amazingData).then(function (processedData) { // both amazingData and processedData are in scope here }); }


Puede marcar Observable representado por Rxjs , le permite devolver más de un valor.


Simplemente haga un objeto y extraiga argumentos de ese objeto.

let checkIfNumbersAddToTen = function (a, b) { return new Promise(function (resolve, reject) { let c = parseInt(a)+parseInt(b); let promiseResolution = { c:c, d : c+c, x : ''RandomString'' }; if(c===10){ resolve(promiseResolution); }else { reject(''Not 10''); } }); };

Extraiga argumentos de la promesaResolución.

checkIfNumbersAddToTen(5,5).then(function (arguments) { console.log(''c:''+arguments.c); console.log(''d:''+arguments.d); console.log(''x:''+arguments.x); },function (failure) { console.log(failure); });


solo puede pasar un valor, pero puede ser una matriz con valores múltiples dentro, por ejemplo:

function step1(){ let server = "myserver.com"; let data = "so much data, very impresive"; return Promise.resolve([server, data]); }

por otro lado, puede usar la expresión de desestructuración para ES2015 para obtener los valores individuales.

function step2([server, data]){ console.log(server); // print "myserver.com" console.log(data); // print "so much data, very impresive" return Promise.resolve("done"); }

llamar a ambos promesa, encadenándolos:

step1() .then(step2) .then((msg)=>{ console.log(msg); // print "done" })


No puede resolver una promesa con múltiples propiedades al igual que no puede devolver múltiples valores de una función . Una promesa representa conceptualmente un valor a lo largo del tiempo, por lo que si bien puede representar valores compuestos, no puede poner varios valores en una promesa.

Una promesa se resuelve inherentemente con un solo valor: esto es parte de cómo funciona Q, cómo funciona la especificación Promises / A + y cómo funciona la abstracción .

Lo más cercano que puede obtener es usar Q.spread y return arrays o usar ES6 destructuring si es compatible o está dispuesto a usar una herramienta de transpilación como BabelJS.

En cuanto a pasar el contexto a una cadena de promesa, consulte el excelente canónico de Bergi sobre eso .