我有一個像這樣的貓鼬模型:
const centerSchema = mongoose.Schema({
centerName: {
type: String,
required: true,
},
candidates: [
{
candidateName: String,
voteReceived: {
type: Number,
default: 0,
},
candidateQR: {
type: String,
default: null,
},
},
],
totalVote: {
type: Number,
default: 0,
},
centerQR: String,
});
我有一個像這樣的 Node.JS 控制器功能:
exports.createCenter = async (req, res, next) => {
const newCenter = await Center.create(req.body);
newCenter.candidates.forEach(async (candidate, i) => {
const candidateQRGen = await promisify(qrCode.toDataURL)(
candidate._id.toString()
);
candidate.candidateQR = candidateQRGen;
// ** Tried these: **
// newCenter.markModified("candidates." i);
// candidate.markModified("candidateQR");
});
// * Also tried this *
// newCenter.markModified("candidates");
const upDatedCenter = await newCenter.save();
res.status(201).json(upDatedCenter);
};
簡單地說,我想修改子檔案上的 CandidateQR 欄位。結果應該是這樣的:
{
"centerName": "Omuk Center",
"candidates": [
{
"candidateName": "A",
"voteReceived": 0,
"candidateQR": "some random qr code text",
"_id": "624433fc5bd40f70a4fda276"
},
{
"candidateName": "B",
"voteReceived": 0,
"candidateQR": "some random qr code text",
"_id": "624433fc5bd40f70a4fda277"
},
{
"candidateName": "C",
"voteReceived": 0,
"candidateQR": "some random qr code text",
"_id": "624433fc5bd40f70a4fda278"
}
],
"totalVote": 0,
"_id": "624433fc5bd40f70a4fda275",
"__v": 1,
}
但是我在 Database 中得到的 CandidateQR 仍然為空。我嘗試了 markModified() 方法。但這并沒有幫助(如上面代碼的注釋部分所示)。我沒有收到任何錯誤訊息。作為回應,我得到了預期的結果。但是該結果并未保存在資料庫中。我只想更改候選二維碼欄位。但無法弄清楚如何。
uj5u.com熱心網友回復:
您可以使用 eachSeries 而不是 forEach 回圈。
const async = require("async");
exports.createCenter = async (req, res, next) => {
const newCenter = await Center.create(req.body);
async.eachSeries(newCenter.candidates, async (candidate, done) => {
const candidateQRGen = await promisify(qrCode.toDataURL)(
candidate._id.toString(),
);
candidate.candidateQR = candidateQRGen;
newCenter.markModified("candidates");
await newCenter.save(done);
});
res.status(201).json(newCenter);
};
uj5u.com熱心網友回復:
據我了解,您只是在遍歷候選陣列,但沒有存盤更新后的陣列。您還需要將更新的資料存盤在變數中。請使用地圖嘗試以下解決方案。
exports.createCenter = async (req, res, next) => {
const newCenter = await Center.create(req.body);
let candidates = newCenter.candidates;
candidates = candidates.map(candidate => {
const candidateQRGen = await promisify(qrCode.toDataURL)(
candidate._id.toString()
);
return {
...candidate,
candidateQR: candidateQRGen
}
});
newCenter.candidates = candidates;
const upDatedCenter = await newCenter.save();
res.status(201).json(upDatedCenter);
};
uj5u.com熱心網友回復:
你可以先用這個save()
newCenter.markModified('candidates');
uj5u.com熱心網友回復:
forEach 回圈是這里的罪魁禍首。用 for...of 替換 forEach 后,它解決了這個問題。基本上,forEach 采用一個回呼函式,該函式在代碼庫中被標記為異步,它最初回傳一個 Promise 并稍后執行。
至于...of 不采用任何回呼函式,因此它內部的 await 屬于控制器函式的范圍并立即執行。感謝 Indraraj26指出這一點。因此,控制器的最終作業版本將如下所示:
exports.createCenter = async (req, res, next) => {
const newCenter = await Center.create(req.body);
for(const candidate of newCenter.candidates) {
const candidateQRGen = await promisify(qrCode.toDataURL)(
candidate._id.toString()
);
candidate.candidateQR = candidateQRGen;
};
newCenter.markModified("candidates");
const upDatedCenter = await newCenter.save();
res.status(201).json(upDatedCenter);
};
此外,感謝 Moniruzzaman Dipto展示了使用 async.eachSeries() 方法解決問題的不同方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/453625.html
