昨天我問了一個類似的問題,但解決方案非常簡單,并沒有真正解決我不理解異步 JavaScript 中的流控制的基本問題。我正在嘗試做的簡短版本是從 JSON 檔案目錄構建 MongoDB 集合。我讓它作業了,但是我修改了一些東西,現在流程使得程式運行完成,因此在執行異步insertOne()呼叫之前關閉連接。當insertOne()最終執行呼叫時,資料沒有輸入,并且我收到有關使用關閉連接的未處理例外的警告。
我是新手,所以如果我所做的不是最佳實踐(不是),請告訴我,我很樂意改變事情以使其可靠。相關代碼基本上是這樣的:
fs.readDirSync(dataDir).forEach(async function(file){
//logic to build data object from JSON file
console.log('Inserting object ' obj['ID']);
let result = await connection.insertOne(obj);
console.log('Object ' result.insertedId ' inserted.');
})
以上內容包含在async我的功能中await。通過console.log()在程式流程的末尾放置一條訊息,后跟 a while(true);,我已經驗證列印了所有“'Inserting object ' obj[ID]”訊息,但沒有列印以下“'Object ' result.insertedId '在流程到達程式末尾時插入'”訊息。如果我洗掉while(true);我會收到所有錯誤訊息,因為我不再阻塞并且顯然到那時客戶端已關閉。在任何情況下都沒有實際構建資料庫。
我知道總是有學習曲線,但是不能做像流量控制這樣簡單的事情真的很令人沮喪。我只是想做一些簡單的事情,比如“遍歷每個檔案,對每個檔案執行功能,關閉并退出”,這是補救性編程。那么,在所有將資料插入到集合中的嘗試都完成(成功或不成功,因為理想情況下我可以使用標志來標記是否有任何錯誤)之前,標記流控制不會通過的點的最佳方法是什么?
uj5u.com熱心網友回復:
我找到了一點答案。這是一個 hack,但是在網上進一步搜索并且缺乏回應表明可能沒有真正好的方法來可靠地使用異步代碼和回呼控制流。基本上,修改大致如下:
fs.readDirSync(dataDir).forEach(async function(file){
jobsOutstanding ;
//logic to build data object from JSON file
console.log('Inserting object ' obj['ID']);
let result = await connection.insertOne(obj);
console.log('Object ' result.insertedId ' inserted.');
jobsOutstanding--;
})
wherejobsOutstanding是帶有訪問器的模塊的頂級變數,numJobsOutstanding().
我現在像這樣包裝關閉(通過一些日志記錄來觀察流程是如何作業的):
async function closeClient(client){
console.log("Enter closeClient()");
if(!client || !client.topology || !client.topology.isConnected()){
console.log("Already closed.");
}
else if(dataObject.numJobsOutstanding() == 0){
await client.close();
console.log("Closed.");
}
else{
setTimeout(function(){ closeClient(client);}, 100);
}
}
我讓這個正確運行,并且日志記錄對于可視化異步佇列很有趣。我不會接受這個答案,看看是否有人知道更好的東西。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/406702.html
標籤:
上一篇:用于跨陣列計算分布的聚合
