2016-07-31 55 views
0

我试图在问题和答案之间建立关联。我正在使用Bluebird的API .map来确保仅在所有question.addAnswers(answer)承诺完成后发生重定向。因此,在我的终端,我看到这样的事情:Bluebird Promise.map无法正常工作

done adding a answer to the question 
done adding a answer to the question 
finished 

不过,我看到的是:

finished 
done adding a answer to the question 
done adding a answer to the question 

因此,我假设Promise.map是不工作的。我错过了什么?我怎样才能使它工作?

这里是我的代码:

router.post('/create', function(req, res) { 
    models.Question.create({ 
    content: req.body.question 
    }) 
    .then(function(question) { 
    if (!question) { 
     res.render('questions/new', { 
      error: "Question \"#{req.body.question}\" fails to be created" 
     }); 
    } else { 
     // Update the new question to each user 
     models.User.findAll() 
     .then(function(users) { 
     users.forEach(function(user) { 
      user.addQuestion(question) 
     }); 
     }); 
     Promise.map(req.body.answers, function(answer){ 
     return createAndAddToQuestion(question, answer, res) 
     }) 
     .then(function(){ 
     console.log('finished') 
     res.redirect("https://stackoverflow.com/questions/success/?question_id=" + question.id); 
     }); 
    }; 
    }) 
}) 

var createAndAddToQuestion = function(question, answer, res) { 
    models.Answer.create({ 
    content: answer 
    }) 
    .then(function(ans) { 
    if (ans) { 
     var promise = question.addAnswer(ans) 
     promise.then(function(){ 
     console.log("done adding a answer to the question") 
     }); 
     return question.addAnswer(ans); 
    } else { 
     res.render('questions/new', { 
     error: "Answer \"#{answer}\" fails to be created" 
     }); 
    }; 
    }); 
} 

UPDATE 我刚刚更新createAndAddToQuestion,所以它会返回一个承诺来代替。结果保持不变。 Promise.map不起作用。

var createAndAddToQuestion = function(question, answer, res) { 
    models.Answer.create({ 
    content: answer 
    }) 
    .then(function(ans) { 
    if (ans) { 
     return question.addAnswer(ans).then(function() { 
     console.log('done') 
     }) 
    } else { 
     res.render('questions/new', { 
     error: "Answer \"#{answer}\" fails to be created" 
     }); 
    }; 
    }); 
} 
+0

'createAndAddToQuestions'不会返回任何东西,但大概你希望它返回某种类型的Promise。也许你只是想'返回models.Answer.create ...'? – smarx

+0

此外,您可能希望'return promise'而不是'return question.addAnswer(ans)'...否则,您将调用该函数两次。 – smarx

+0

谢谢!这是一个错字。我将它改回来,但结果相同。 @smarx – WeiRoR

回答

0

你最突出的问题是,createAndAddToQuestion不返回一个承诺,所以map不知道等待什么。

此外,您不等models.User.findAll,调用question.addAnswer(ans);两次,可能会尝试多次呈现错误消息,如果答案未能创建,并且没有通用错误处理程序。你应该做的

router.post('/create', function(req, res) { 
    createQuestion(req.body).then(function(question) { 
    console.log('finished') 
    res.redirect("https://stackoverflow.com/questions/success/?question_id=" + question.id); 
    }, function(err) { 
    res.render('questions/new', { 
     error: err.message 
    }); 
    }).catch(function(err) { 
    console.error(err); 
    res.status(500); 
    }); 
}); 

function createQuestion(opts) { 
    return models.Question.create({ 
    content: opts.question 
    }) 
    .then(function(question) { 
    if (!question) { 
     throw new Error("Question \"#{opts.question}\" fails to be created"); 
    } 
    // Update the new question to each user 
    return Promise.all([ 
     models.User.findAll() 
     .then(function(users) { 
     users.forEach(function(user) { 
      user.addQuestion(question) 
     }) 
     }), 
     Promise.map(opts.answers, function(answer){ 
     return createAndAddToQuestion(question, answer) 
     }) 
    ]).return(question); 
    }); 
} 

function createAndAddToQuestion(question, answer) { 
    return models.Answer.create({ 
    content: answer 
    }) 
    .then(function(ans) { 
    if (!ans) { 
     throw new Error("Answer \"#{answer}\" fails to be created"); 
    } 
    return question.addAnswer(ans); 
    }) 
    .then(function(){ 
    console.log("done adding a answer to the question") 
    }); 
} 
+0

我试过了,错误返回:'未处理的拒绝SequelizeDatabaseError:ER_BAD_FIELD_ERROR:'where子句'中的未知列'NaN' 另外,我没有故意等待'user.findAll()',因为我没有当我重定向时需要该方法的结果。我是否必须等待它完成,尽管我不需要马上得到结果?这样可以节省一些时间。在这种情况下,我的原始代码应该可行,对吗? 另外,在你的代码中,问题如何通过'createQuestion'的路径传递?'question.addAnswer'会在其承诺中返回问题吗? – WeiRoR

+0

@WeiRoR:感谢提示,更新了我的答案。我的确忘记了从助手功能中返回问题。那里的数据库错误来自我不知道,但它是一个未处理的拒绝确实让我担心。关于findAll,我仍然会等待它,以便可以从执行中捕获错误。尽管如此,您可以将其与其他操作并行执行。 – Bergi

+0

这是有效的。非常感谢!你能否解释一下这个问题是如何通过'Promise.all([...])返回的。return(question)'?另外,在路由中,'.then(...)'中的'function(err){...}'来自哪里?我认为'.then(...)'里通常只有一个函数。 – WeiRoR