javascript - 如何使用 async/await 在 Express 中完成这项工作
问题描述
我正在从 MongoDB 服务器中的项目中读取文件名列表,然后检查本地存储中是否存在这些文件名。我正在尝试创建所有匹配文件名的列表,这些文件名同时存在于本地和数据库中,然后在 Express 响应中发送该列表。
这就是我想出的。
app.get('/api/album', (req, res) => {
let matches = [];
Album.find({}).then(albums => {
albums.forEach( (item, index) => {
fs.readdir('./static/img/album-art/', (err, files) => {
files.forEach(file => {
if (file !== undefined && item.coverUrl !== undefined) {
if (file == item.coverUrl) {
matches.push(item.name);
}
}
});
});
});
});
res.json(matches);
});
但是,响应只包含一个空列表,因为fs.readdir()
它是异步的。我想让它保持异步,但我正试图找到一种在完成后发送响应的方法。我不擅长承诺,我知道我可以async/await
在这里使用,但我无法让它发挥作用。
解决方案
您可以使用对库的内置承诺支持,fs
并且还可以避免双重嵌套循环,您可以将文件列表放入 aSet
以便更有效地检查每个项目:
const fsp = require('fs').promises;
app.get('/api/album', async (req, res) => {
let matches = [];
try {
let albums = await Album.find({});
let files = await fsp.readdir('./static/img/album-art/');
let filesSet = new Set(files);
let matches = [];
for (let item of albums) {
if (filesSet.has(item.coverUrl)) {
matches.push(item.name);
}
}
res.json(matches);
} catch(e) {
console.log(e);
res.sendStatus(500);
}
});
根据您的代码,我假设它item.coverUrl
实际上只是一个基本文件名mysong.jpg
,而不是实际的 URL,因为实际的完全限定 URL 永远不会匹配其中一个文件名。
仅供参考,您不需要任何一项undefined
检查。该files
数组永远不会包含undefined
值,因此即使item.coverUrl
is undefined
,它也永远不会匹配其中一个文件,因此它会以这种方式照顾自己,因为它永远不会匹配。
推荐阅读
- html - 属性“linktext”的目的是什么?
- amazon-web-services - 如何通过 shell 访问 Amazon Keyspaces?
- php - 用于在 Wordpress 的自定义存档页面中过滤自定义帖子类型的文本输入字段
- bert-language-model - 如何连接 HuggingFace 中特殊标记和单词的词嵌入?
- postgresql - PostgresSQL 9.5 安装失败:“数据库集群初始化失败” MAC os (big sur 11.4)
- spring - 使用 Thymeleaf 的 Spring Webflux 中的 Blockhound 异常
- react-native - Jest React Native,测试/模拟?布局
- php - 在 php 中使用 in_array 时缺少一个值
- apache-spark - PySpark 性能问题
- python - 逐行加入两个熊猫数据框列