Tengo el siguiente código para probar la ejecución asíncrona en Javascript, usando promesas y tiempos de espera:
'use strict' const { promisify } = require('util') const print = (err, contents) => { if (err) console.error(err) else console.log(contents) } const opA = (cb) => { setTimeout(() => { cb(null, 'A') }, 500) } const opB = (cb) => { setTimeout(() => { cb(null, 'B') }, 250) } const opC = (cb) => { setTimeout(() => { cb(null, 'C') }, 125) } const opAProm = promisify(opA) const opBProm = promisify(opB) const opCProm = promisify(opC) opAProm(print).then((res) => opBProm(print).then((res) => opCProm(print)))El resultado que esperaría es este:
A B CPero en cambio, se imprime solo esto:
AHe buscado una solución y la más similar que he encontrado es esta, aunque realmente no me ha ayudado: Promesas de Javascript: entonces () no son síncronas
Entonces, me gustaría saber cómo puedo resolver esto, usando promesas o async/await. ¡Gracias por adelantado!
Después de prometer algo, no debe pasarle una devolución de llamada ; más bien, solo llame a .then en la Promesa resultante. Si elimina la print s de las líneas como estas:
opAProm(print)y en su lugar encadene la Promesa directamente, funcionará como se desee.
opAProm().then((resultA) => { print(resultA); opBProm().then((resultB) => { print(resultB); opCProm() .then((resultC) => { print(resultC); }); }) });O, un mejor enfoque:
opAProm() .then((resultA) => { print(resultA); return opBProm(); }).then((resultB) => { print(resultB); return opCProm(); }) .then((resultC) => { print(resultC); }); (o use async / await )
De lo contrario, si lo hace (como en su código original)
opAProm(print) Luego, se infiere que cb es la función pasada, cb para opA , que no está conectada a Promise, por lo que el encadenamiento adicional no funciona. Con la promesa de util, la devolución de llamada que reemplaza la promesa debe ser el argumento final de la función original: si le pasa otro argumento en combinación, se descontrolará. A menos que cambie las funciones originales para aceptar dos argumentos, lo que sería realmente extraño, pero "funcionaría".
const opA = (cb, finalcb) => { setTimeout(() => { cb(null, 'A') finalcb(); }, 500) } const opB = (cb, finalcb) => { setTimeout(() => { cb(null, 'B') finalcb(); }, 250) } const opC = (cb, finalcb) => { setTimeout(() => { cb(null, 'C') finalcb(); }, 125) } const opAProm = promisify(opA) const opBProm = promisify(opB) const opCProm = promisify(opC) opAProm(print) .then(() => { return opBProm(print); }).then(() => { return opCProm(print); });Promisify elimina la última función de callback de llamada. Es decir, el método de print pasado es inútil aquí. En lugar de eso, obtendrá el resultado en la función then/resolve e imprimir. Como mencionó @CertainPerformance, puede convertir para usar promesa con imprimir en ese momento o usar async-await para simplificar.
const { promisify } = require("util"); const print = (err, contents) => { if (err) console.error(err); else console.log(contents); }; const opA = (cb) => { setTimeout(() => { cb(null, "A"); }, 500); }; const opB = (cb) => { setTimeout(() => { cb(null, "B"); }, 250); }; const opC = (cb) => { setTimeout(() => { cb(null, "C"); }, 125); }; const opAProm = promisify(opA); const opBProm = promisify(opB); const opCProm = promisify(opC); async function main() { const resA = await opAProm(); console.log(resA); const resB = await opBProm(); console.log(resB); const resC = await opCProm(); console.log(resC); } main();