tutorial - ¿Hay formas idiomáticas de expresar "if(c1 || c2)" en JavaScript cuando una de las condiciones es una promesa y la otra no?
then javascript (3)
Cuando solo realizo los siguientes pasos en mi algoritmo si se cumplen varias condiciones, lo expreso de esta manera:
if (sc1 || sc2) {
do();
various();
things();
}
Cuando solo realizo los siguientes pasos basados en el cumplimiento de una promesa, puedo expresarlo así:
asyncCheck().then(ac1 => {
if (ac1) {
do();
various();
things();
}
}
¿Cómo puedo expresar en lenguaje idiomático JavaScript cuando la condición sc1
es solo una antigua expresión sincrónica normal, pero la condición ac2
viene asincrónicamente a través de una promesa?
Asuma promesas de ES6 nativas y código no trivial que se ejecuta si se cumplen las condiciones.
Por ejemplo, esta forma "obvia" parece fea:
if (sc1) {
do();
various();
things();
} else {
asyncCheck().then(ac2 => {
if (ac2) {
do();
various();
things();
}
}
}
Podría poner el código repetido en una función que se llame de cualquier manera, lo cual es menos feo, pero siento que podría estar perdiendo algo más idiomático que otros programadores de JavaScript podrían estar usando.
Debo añadir esta observación también: dado que en mi caso, existe un cortocircuito lógico o cortocircuito, por lo que no debería molestarse con el control diferido lento si la verificación simple ya es false
.
Bueno, no, promesas solo valores abstractos. Si bien es posible expresar estructuras de flujo de control con promesas, no creo que sea una buena idea.
function or(v1, v2, ifPath, elsePath) {
v1 = Promise.resolve(v1);
v2 = Promise.resolve(v2);
return Promise.all([v1, v2])
.then(([v1, v2]) => (v1 || v2) ? ifPath() : elsePath());
}
Que te dejaría hacer:
or(ac1, ac2, () => {
do();
various();
things();
}, () => {});
Pero, sinceramente, esa es una idea bastante mala en general. Tiene fugas (no hay cortocircuito) y no se combina con otras abstracciones. Puedes hacer un trabajo mucho más básico:
Promise.all([ac1, ac2]).then(([r1, r2]) => {
if(r1 || r2) {
do();
various();
things();
}
});
Lo cual es más fácil y fácil de componer. En la próxima versión de JavaScript (ES8, ES2017) es muy probable que tenga async
/ await
que le permita hacer lo siguiente directamente:
// the function containing this needs to be marked as `async`
if (sc1 || await sc2) {
do();
various();
things();
}
Lo cual hará las cosas más fáciles. Esto sigue siendo un poco permeable, pero mucho menos.
Muy simple en realidad:
Promise.resolve(sc1 || asyncCheck()).then(cond => {
if (cond) {
do();
various();
things();
}
});
Es cierto que la veracidad de sc1
posiblemente se evalúe dos veces, pero de lo contrario se produce un cortocircuito. También puedes usar
(sc1 ? Promise.resolve(true) : asyncCheck()).then(cond => { … });
Pensando más y con la ayuda de todos aquí, esta es mi evolución actual:
function ifConditionsMet() {
if (sc1) {
return Promise.resolve(true);
} else {
return asyncCheck();
}
}
ifConditionsMet().then(() => {
do();
various();
things();
});
Esto esto debería funcionar bien con cualquier manejo de excepción también ...