trabajar promesas nodejs node encadenamiento done defer con anidadas node.js callback promise q

promesas - ¿Cómo optimizar este código de Node.js+q para evitar el infierno de devolución de llamada?



q defer() node js (3)

Sí, una forma de limpiarlo sería definir una función con nombre:

function SuccessfulSend(result) { if (result == constants.EVENT_EMIT_SENT) { appLog.debug("Message [%s] sent!!!", msg._id); messageService.remove(msg._id) .then(function(result) { appLog.debug("Message deleted: [%s]", msg._id); }) .fail(function(err) { appLog.error("The message couldn''t be deleted: [%s]", msg._id); }); }else if (result == constants.EVENT_EMIT_NOT_SENT_AND_NOT_STORED) { appLog.debug("Message [%s] not sent", msg._id); } }

y entonces:

.then(SuccessfulSend);

Estoy usando Q para prevenir el infierno de devolución de llamada, pero he llegado a una parte de mi código que no sé cómo organizar:

Estoy buscando mensajes programados para ser entregados. Para cada uno de ellos, trato de enviarlos uno por uno y si se pueden enviar, los quita de la base de datos. La parte fea es tener un then () dentro de un ciclo for . ¡De esta forma termino anidando promesas en lugar de callbacks anidados! Sugerencias?

appLog.debug("Looking for scheduled messages"); var messages = messageService.findScheduled() .then(function(messages){ appLog.debug("found [%d] stored messages",messages.length); for(var i = 0; i<messages.length; i++){ messageService.send(msg.namespace, msg.message, msg.data) .then(function(result) { if (result == constants.EVENT_EMIT_SENT) { appLog.debug("Message [%s] sent!!!", msg._id); messageService.remove(msg._id) .then(function(result) { appLog.debug("Message deleted: [%s]", msg._id); }) .fail(function(err) { appLog.error("The message couldn''t be deleted: [%s]", msg._id); }); }else if (result == constants.EVENT_EMIT_NOT_SENT_AND_NOT_STORED) { appLog.debug("Message [%s] not sent", msg._id); } }); } });


Simplemente refactorizar sus funciones en funciones nombradas y tratar de hacer un mejor uso del encadenamiento prometedor sería una gran mejora.

var messageService, appLog, constants; appLog.debug("Looking for scheduled messages"); messageService.findScheduled() .then(function(messages){ appLog.debug("found [%d] stored messages", messages.length); messages.map(processMessage); }); function processMessage(msg) { msg.data.dontStore = true; messageService .send(msg.namespace, msg.message, msg.data) .then(function(result) { if (result !== constants.EVENT_EMIT_SENT) { throw new Error(constants.EVENT_EMIT_SENT); } appLog.debug("Message [%s] sent!!!", msg._id); return removeMessage(msg); }) .fail(function(err) { appLog.debug("Message [%s] not sent", msg._id); throw err; }); } function removeMessage(msg) { return messageService.remove(msg._id) .then(function() { appLog.message("Message deleted: [%s]", msg._id); }) .fail(function(err) { appLog.message("The message couldn''t be deleted: [%s]", msg._id); throw err; }); }


La parte fea es tener un then () dentro de un bucle for

No, eso puede suceder. Aunque el estilo de programación funcional de las promesas generalmente lleva a utilizar .map() con una devolución de llamada de todos modos :-) La bucle es una estructura de control y requiere anidamiento (excepto que se usan excepciones para el flujo de control , es decir, bifurcación). Sin embargo, lo que no tienes que hacer es anidar promesas en callbacks de promesas.

Simplificaría tu cuerpo de bucle para

function sendAndDelete(msg) { return messageService.send(msg.namespace, msg.message, msg.data) .then(function(result) { if (result == constants.EVENT_EMIT_SENT) { appLog.debug("Message [%s] sent!!!", msg._id); return msg._id; } else if (result == constants.EVENT_EMIT_NOT_SENT_AND_NOT_STORED) { appLog.debug("Message [%s] not sent", msg._id); throw new Error("Message not sent"); } }) .then(messageService.remove) .then(function(result) { appLog.debug("Message deleted: [%s]", msg._id); }, function(err) { appLog.error("The message has not been deleted: [%s]", msg._id); }); }

Ahora puedes hacer algo como

messageService.findScheduled() .then(function(messages){ appLog.debug("found [%d] stored messages",messages.length); return Q.all(messages.map(sendAndDelete)); }) .then(function() { appLog.debug("all messages done"); });