如何使用 async/await 在 Express 中完成这项工作

Posted

技术标签:

【中文标题】如何使用 async/await 在 Express 中完成这项工作【英文标题】:How can I use async/await to make this work in Express 【发布时间】:2020-06-14 10:18:51 【问题描述】:

我正在从 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,但我无法让它发挥作用。

【问题讨论】:

这能回答你的问题吗? Using filesystem in node.js with async / await 【参考方案1】:

您可以使用对fs 库的内置承诺支持,并且为了避免双重嵌套循环,您可以将文件列表放在Set 中,以便更有效地检查每个项目:

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.coverUrlundefined,它也永远不会匹配其中一个文件,因此它会以这种方式照顾自己,因为它永远不会匹配。

【讨论】:

【参考方案2】:

您可以使用 readdirSync() 同步方式来读取目录。

【讨论】:

从不建议在服务器请求处理程序中使用同步 I/O,因为它会阻塞事件循环并破坏服务器的可伸缩性。它仅适用于服务器启动代码或非服务器脚本,如果您阻止整个事件循环无关紧要。【参考方案3】:

“util”库应该按照以下答案的建议来解决问题。

Using filesystem in node.js with async / await

【讨论】:

以上是关于如何使用 async/await 在 Express 中完成这项工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mongoose 中使用 async/await

Javascript 如何在 mysql 中使用 Async/Await

JS255- 如何在 JS 循环中正确使用 async 与 await

如何在 Vue.js 中使用 async/await?

在 Angular 中,如何在使用 async/await 时处理 Promise 拒绝

如何在 Gulp 4 中使用 async/await?