使用 npm exiftool (javascript) 异步问题

using npm exiftool (javascript) async problem

我在使用 npm exiftool 时遇到问题。 (https://www.npmjs.com/package/exiftool)我正在尝试使用它做一些事情。

  1. 通过特定文件夹迭代图像文件
  2. 获取每个图像文件的'xpKeywords'个数据。
  3. 写文件存储数据。

这是我的代码。

const fs = require('fs');
const exif = require('exiftool');
const folderName = 'testImages';
const inputPath = `/Users/myName/Project/project/${folderName}`;
const files = fs.readdirSync(inputPath, 'utf8');

let data = [];

(async () => {
  let promises = [];
  files.forEach(file => promises.push(fs.readFileSync(`${inputPath}/${file}`)));
  let results = await Promise.all(promises);
  for(let [index, result] of results.entries()) {
    let datum = await getMetadata(result, index);
    console.log("out");
    data.push(datum);
  }
  fs.writeFileSync('outputData/metaData.json', JSON.stringify(data, null, 4), (error) => {
    console.log('Error Occurred');
  });
})();

async function getMetadata(result, index) {
  console.log(`get metadata ${index}`);
  await exif.metadata(result, (err, metadata) => {
    return {
      name: files[index],
      hashTags: metadata.xpKeywords
    };
  });
}

在 运行 该代码之后,文件 metaData.json 不是我所期望的。

[ 无效的, 无效的, 无效的, 无效的, 无效的, 无效的 ]

我想我在函数 getMetadata 中使用异步函数时遇到了一些问题。

那里有几个问题。

  • 最主要的是 getMetaData 没有 return 任何东西。从您提供的 回调 返回 exif.metadata 不会执行任何操作来设置 getMetaData.
  • 的 return 值
  • 另外,fs.readFileSync 没有 return 承诺,因此 let results = await Promise.all(promises); 调用没有意义。 (顾名思义,它同步工作。)
  • 通过索引将文件引用到全局模块中很容易出错。

要使用 promises,您可以在 fs.readFile 上使用 Node.js 的当前实验性 promises file API, or use util.promisify(该版本实际上是异步的,使用回调)。如果您想获得启用承诺的版本,也可以在 exif.metadata 上使用 promisify

This question's answers 详细了解如何将基于回调的 API 转换为 Promise。

牢记所有这些,我认为您正在寻找符合这些思路的东西(可能需要调整):

const fs = require('fs');
const {promisify} = require('util');
const exif = require('exiftool');

const pReaddir = promisify(fs.readdir);
const pReadFile = promisify(fs.readFile);
const pWriteFile = promisify(fs.writeFile);
const pMetadata = promisify(exif.metadata);

const folderName = 'testImages';
const inputPath = `/Users/myName/Project/project/${folderName}`;

(async () => {
    // Get the file names
    const files = await pReaddir(inputPath, 'utf8');
    // Process the files in parallel and wait for the result
    const data = Promise.all(files.map(async(name) => {
        // Read this file and get its metadata from it
        let {xpKeywords: hashTags} = await pMetadata(await pReadFile(`${inputPath}/${name}`));
        // Return an object with the file's name and xpKeywords as its hashTags
        return {name, hashTags};
    }));
    // Write the results to file
    await pWriteFile('outputData/metaData.json', JSON.stringify(data, null, 4));
})()
.catch(error => {
    console.error(error);
});