使用npm exiftool(javascript)异步问题

时间:2019-03-09 12:41:16

标签: javascript npm exiftool

我在使用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函数中使用异步函数遇到一些麻烦。

1 个答案:

答案 0 :(得分:0)

那里有几个问题。

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

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

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);
});