2016-07-31 62 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