我構建了一個抓取器,將抓取的資料與現有資料進行比較以避免重復,創建新條目并更新舊條目。我正在使用 for 回圈執行此操作,該回圈遍歷 findOne 函式,其中有兩個等待。問題是我的 for 回圈忽略了(因為它是同步的?)我的等待并轉到重要的部分所有這些等待都完成了。
async function comparedata(length) {
console.log("Starting comparing entries in data");
for (let x = 0; x < length; x ) {
const model = new dataModel({
link: dataLinks[x],
name: dataGames[x].replace('Download', ' '),
logo: dataLogos[x],
provider: 'data',
});
model.collection.findOne({ "link": dataLinks[x] }, async function (err, found) {
if (err) throw err;
if (found == null) {
await model.save().then((result) => {
console.log(result) // Is not happening because the for loop goes through to the next function and closes the server
}).catch((err) => { console.log(err) });
}
else if (found != null) {
if (dataGames[x] != found.name) {
await model.collection.findOneAndUpdate({ link: dataLinks[x] }, { $set: { name: dataGames[x] } });
}
}
})
}
closeServer()//Closes the server is happening before new entries or updates are made.
}
我的想法是使用 promises,但即使我嘗試這樣做,它也只是解決得太快并再次關閉服務器。
uj5u.com熱心網友回復:
你應該能夠像這樣簡化你的邏輯:
async function comparedata(length) {
console.log('Starting comparing entries in data');
try {
for (let x = 0; x < length; x ) {
let found = await dataModel.findOne({ link: dataLinks[x] });
if (!found) {
found = await dataModel.create({
link: dataLinks[x],
name: dataGames[x].replace('Download', ' '),
logo: dataLogos[x],
provider: 'data',
});
} else if (found.name !== dataGames[x]) {
found.name = dataGames[x];
await found.save();
}
console.log(found);
}
} catch (e) {
console.log(e);
}
closeServer();
}
uj5u.com熱心網友回復:
對于 for 回圈的第一次迭代,findOne 的回呼被事件回圈放入回呼佇列中,它繼續進行下一次迭代而不等待等待,直到最后一次迭代,最后一次迭代后它立即呼叫 closeServer (),在這個closeServer() 呼叫之后放入回呼佇列的任務(即findOne 的回呼)被事件回圈考慮和執行。為了理解這一點,您必須了解事件回圈以及事件回圈如何執行 javascript 代碼。請在此處查看事件回圈作業機制youtube 視頻
您可以使用 findOne 的 promise 風格執行來解決這個問題。
根據我的說法,在同一條陳述句上使用 await & then() 功能并不是一個好習慣。
我的建議,
async function comparedata(length) {
console.log("Starting comparing entries in data");
for (let x = 0; x < length; x ) {
const model = new dataModel({
link: dataLinks[x],
name: dataGames[x].replace('Download', ' '),
logo: dataLogos[x],
provider: 'data',
});
// using .exec() at the end allows us to go with the promise way of dealing things rather than callbacks
// assuming that 'dataModel' is the Schema, so I directly called findOne on it
const found = await dataModel.findOne({ "link": dataLinks[x] }).exec();
if (found == null) {
// wrap the await in try...catch for catching errors while saving
try{
await model.save();
console.log("Document Saved Successfully !");
}catch(err) {
console.log(`ERROR while saving the document. DETAILS: ${model} & ERROR: ${err}`)
}
} else if (found != null) {
if (dataGames[x] != found.name) {
await model.collection.findOneAndUpdate({ link: dataLinks[x] }, { $set: { name: dataGames[x] } });
}
}
if (x > length)
sendErrorMail();
}
closeServer()//Closes the server is happening before new entries or updates are made.
}
注意:請參閱 Mongoose官方檔案以獲取更新。
uj5u.com熱心網友回復:
我對 mongoose api 不是很熟悉,但是如果你無法使用 promisified 版本,那么你可以使用 Promise 建構式“跳出”回呼:
const found = await new Promise((resolve, reject) => {
model.collection.findOne({ "link": dataLinks[x] }, function (err, found) {
if (err) {
reject(err);
return;
};
resolve(found);
}
});
這可能會幫助您解決問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/536445.html
上一篇:在“mongodb-connection-string-url”中出現錯誤
下一篇:Ktor中的服務器正常運行時間
