![](/img/trans.png)
[英]How to use callback in JS (node) to wait for Async function to finish before proceeding?
[英]NODE JS: How can I make the following call wait for the called function to finish before proceeding
我仍然無法將注意力集中在 async/await 功能上,並且針對以下情況嘗試了幾種解決方案,但均未成功:
我有這個 function:
function addDataToDb(articleData) {
initMongoDb();
kanpionDb.on('error', console.error.bind(console, 'connection error:'));
kanpionDb.once('open', function () {
SiteUrlModel.init().then(() => {
articleData.forEach(articleItem => {
var article = new SiteUrlModel(articleItem).save(function (error) {
if (error) {
console.log("Failed: " + articleItem.siteName);
} else {
console.log("Success " + articleItem.siteName);
}
});
});
});
});
}
從另一個文件中調用它:
c.on('drain', async function () {
Database.addDataToDb(ArticleList);
console.log("All done");
});
問題:如何使console.log("All done")
僅在Database.addDataToDb(ArticleList)
完成執行后顯示消息?
這個解決方案有點混亂,因為你有大量的異步技術混合在同一個 function 中:事件、承諾和回調,然后最重要的是,有一個循環。 這確實是一團糟,通常是您想要避免的。
這種復雜程度的最佳整體解決方案是備份幾個步驟,並承諾所有基本異步操作比這高幾個步驟。 對於您的數據庫,您應該 go 找到並使用 promise 接口到數據庫。 對於您的事件,由於這些都是一次性事件,您可以在 object 上構建 promise 包裝器,以獲取有關打開和錯誤事件的通知。
但是,由於我不知道您正在使用的所有組件,因此我無法真正為您完成這部分工作。 因此,我們將看看我們可以做些什么來將適當的 Promise 級別的支持修補到這種混合技術中。
const {promisify} = require('util');
function addDataToDb(articleData) {
return new Promise((resolve, reject) => {
initMongoDb();
kanpionDb.on('error', err => {
console.error('connection error:', error);
reject(error);
});
kanpionDb.once('open', function () {
SiteUrlModel.init().then(() => {
return Promise.all(articleData.map(articleItem => {
let model = new SiteUrlModel(articleItem);
model.savePromise = promisify(model.save);
return model.savePromise().then(() => {
console.log("Success " + articleItem.siteName);
}).catch(err => {
console.log("Failed: " + articleItem.siteName);
throw err;
});
}));
}).then(resolve, reject);
});
});
}
// usage:
addDataToDb(articleData).then(() => {
console.log("All Done");
}).catch(err => {
console.log(err);
});
技術總結:
.forEach()
循環被Promise.all(articleData.map(...))
替換,這將給我們一個 promise 告訴我們所有保存何時完成。.save(callback)
必須替換為.save()
的承諾版本。 理想情況下,您只需在此處使用數據庫接口的承諾版本,但我已經展示了如何在必要時手動承諾.save()
function。error
事件。SiteUrlModel.init()
promise。Promise.all()
promise 鏈接到SiteUrlModel.init()
promise。如果你可以請試試這個,
const saveData = (articleItem) => {
return new Promise((resolve, reject) => {
var article = new SiteUrlModel(articleItem).save(function (error) {
if (error) {
console.log("Failed: " + articleItem.siteName);
reject(error);
} else {
console.log("Success " + articleItem.siteName);
resolve('Success');
}
});
});
});
const addDataToDb = (articleData) => {
const list = [];
return new Promise((resolve, reject) => {
initMongoDb();
kanpionDb.on('error', console.error.bind(console, 'connection error:'));
kanpionDb.once('open', function () {
SiteUrlModel.init().then(() => {
articleData.forEach(articleItem => {
list.push(saveData(articleItem);
});
});
});
Promise.all(list).then(response => {
resolve(response);
}).catch(error => {
reject(error);
})
});
};
c.on('drain', async function () {
const result = Database.addDataToDb(ArticleList).then(res => {
console.log("All done");
});
});
我正在嘗試使用香草承諾
您可以使用承諾讓調用者等待您的異步代碼完成。 重構您的addDataToDb
function 以返回 promise 並相應地解析/拒絕 promise。 由於您已將“drain”回調定義為異步 function,因此您可以在回調中使用await
關鍵字以使事情更簡潔:
c.on('drain', async function () {
await Database.addDataToDb(ArticleList);
console.log("All done");
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.