等待写流完成,然后返回函数

时间:2020-09-29 16:08:56

标签: node.js json async-await google-api

我正在尝试从Google云端硬盘中获取多个JSON文件,然后将其导出到代码中的对象中。我正在使用写流在本地创建文件,然后使用JSON.parse()对其进行解析。这是我当前的实现:

function setDB(dbId, dbName) {
    let database = {};
    drive.files.get({
        fileId: dbId,
        alt: 'media'
    }, {responseType: 'stream'}).then(res => {
        console.log(`Writing to ${dbName}.`);
        const db = fs.createWriteStream(dbName);
        res.data.on('end', () => {
            console.log(`Done downloading file ${dbName}.`);
        }).on('error', err => {
            console.error(`Error downloading file ${dbName}.`);
            throw err;
        }).pipe(db).on('finish', () => {
            database = JSON.parse(fs.readFileSync(`./${dbName}`));
        });
    });
    return database;
}

let variable1 = setDB('variable1Id', 'variable1.json');
let variable2 = setDB('variable2Id', 'variable2.json');
let variable3 = setDB('variable3Id', 'variable3.json');

这里的问题是setDB返回undefined,因为函数在文件完成下载并且流完成写入文件之前返回其值。我知道我应该使用某种异步/等待方式,但是我找不到如何或在哪里放置它们。这可能也不是解决此问题的最佳方法,并且我会很乐意听取有关更好地实现此建议,或者使代码更整洁或更美观的任何建议。但是,这里的主要问题是,如何使setDB返回JSON.parse(fs.readFileSync(`./${dbName}`))

1 个答案:

答案 0 :(得分:0)

我重写了您的代码,以返回一个在流finish事件上解析并在流error拒绝的诺言。您的原始代码不会等待您的承诺。

function async setDB(dbId, dbName) {
  const db = fs.createWriteStream(dbName);
  const res = await drive.files.get({
    alt: 'media',
    fileId: dbId,
  }, {responseType: 'stream'});
  console.log(`Writing to ${dbName}.`);
  return new Promise((resolve, reject) => {
    res.data
      .on('end', () => {
        console.log(`Done downloading file ${dbName}.`);
      })
      .on('error', (err) => {
        console.error(`Error downloading file ${dbName}.`);
        reject(err);
      })
      .pipe(db)
      .on('finish', async () => {
        try {
          const fileContent = await fs.readFile(`./${dbName}`);
          resolve(JSON.parse(fileContent));
        } catch (err) {
          reject(err);
        }
      });
  });
}