node.js - NODE JS:如何使以下调用等待被调用函数完成后再继续
问题描述
我仍然无法将注意力集中在 async/await 功能上,并且针对以下情况尝试了几种解决方案,但均未成功:
我有这个功能:
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)
?
解决方案
这个解决方案有点混乱,因为你在同一个函数中混合了大量的异步技术:事件、承诺和回调,然后最重要的是,有一个循环。这确实是一团糟,通常是您想要避免的。
这种复杂程度的最佳整体解决方案是备份几个步骤,并承诺所有基本异步操作比这高几个步骤。对于您的数据库,您应该去查找并使用数据库的 promise 接口。对于您的事件,由于这些都是一次性事件,您可以在对象上构建一个 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);
});
技术总结:
- 由于这些事件,我们将不得不包装一个手动创建的 Promise,我们在完成时解决或拒绝该 Promise。
.forEach()
循环被替换为whichPromise.all(articleData.map(...))
将给我们一个承诺,告诉我们何时完成所有保存。.save(callback)
必须替换为.save()
. 理想情况下,您只需在此处使用数据库接口的承诺版本,但我已经展示了如何在.save()
必要时手动承诺该功能。- 连接拒绝
error
事件。 - 连接决心并拒绝
SiteUrlModel.init()
承诺。 - 将
Promise.all()
承诺与SiteUrlModel.init()
承诺联系起来。
推荐阅读
- mysql - 从一年中的每个月选择注册用户数,但更改时间戳的值会导致错误的计数
- sql - 如何在sql中使用解码部分数字
- angular - 带有滚动内容的Angular 9卡体?
- node.js - nodejs dockerized 应用程序无法连接到 mariadb dockerized 数据库
- c# - 已发布 API 中的错误 在配置中找不到指定的商店提供程序,或者当我在服务器中发布 API 时无效
- spring-cloud-dataflow - 从 application.yaml 读取 Spring Cloud Data Flow Stream 资源
- flutter - ListView.builder 在 alertDialog 中不起作用
- python - Python中的占位符:将多个名称放在一个数组中
- javascript - React Native Navigation 错误:使用有效负载 {"name": 192.168.100.189:19000", "params":{}} 导航的操作未由任何导航器处理
- c++ - 我得到了一个带有“#include”的c++示例代码
"并且有一个我无法理解的错误