我正在使用 Q 来阻止回调地狱,但我已经达到了我不知道如何安排的部分代码:
我正在搜索要传递的预定消息。对于它们中的每一个,我尝试逐个发送它们,如果它可以被发送,则将其从数据库中删除。丑陋的部分是在for循环中有一个 then()。这样我最终得到嵌套的promises而不是嵌套的回调!!!!建议?
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);
}
});
}
});
答案 0 :(得分:1)
丑陋的部分是在for循环中有一个then()
不,那可能发生。虽然promises的函数式编程风格通常会导致.map()
使用回调:-)循环是一个控制结构,并且需要嵌套(除了use exceptions for control flow,即ie分枝)。但是,您不必做的是在承诺回调中嵌套承诺。
我将你的循环体简化为
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);
});
}
现在你可以做类似
的事情了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");
});
答案 1 :(得分:0)
是的,清理它的一种方法是定义一个命名函数:
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);
}
}
然后:
.then(SuccessfulSend);
答案 2 :(得分:0)
简单地将您的函数重构为命名函数,并尝试更好地使用promise链接将是一个巨大的改进。
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;
});
}