8

我正在Node中构建一个服务器,它将搜索一个文件夹以查看XML文件是否存在(glob),如果存在,则将(fs)中的文件作为JSON对象(xml2js)读取并最终将其存储在数据库中某处。我想将解析器的结果输出到另一个变量中,这样我就可以对数据做其他事情了。据我所知,有些东西正在同步运行,但我不知道如何停止它,让我等到它完成后再继续前进。

我将我的功能从 app.js 分离到其他地方的控制器中:

app.controller.js

const fs = require('fs-extra');
const glob = require('glob');
const xml2js = require('xml2js');

exports.requests = {};

exports.checkFileDrop = async () => {
  console.log('Checking for xml in filedrop...');
  // this is the only place await works...
  await glob('./filedrop/ALLREQUESTS-*.xml', (err, files) => {
    var parser = new xml2js.Parser();
    // this is looking for a specific file now, which I'll address later once I can figure out this issue
    fs.readFile('./filedrop/ALLREQUESTS-20170707.xml', 'utf16le', function (err, data) { 
      if (err) {
        console.log('ERROR: ', err);
      } else {
        parser.parseString(data, (err, result) => {
          if (err) {
            console.log('ERROR: ', err);
          } else {
            console.log('data found');
            exports.requests = JSON.stringify(result.Records.Record);
            // data is outputted here correctly
            console.log(exports.requests);
            // this doesn't even seem to want to save to exports.requests anyways...
          }
        });
      }
    });
  });
}

应用程序.js

const appController = require('./controllers/app.controller');

// check if there is file in filedrop
appController.checkFileDrop();
// prints out an empty object
console.log(appController.requests);
// can't do anything if it doesn't exist yet
appController.saveToDB(appController.requests);
4

2 回答 2

16

await将等待一个Promise值解决,否则它只会将它给出的值包装在一个承诺中并立即解决这个承诺。在你的例子中,

await glob('./filedrop/ALLREQUESTS-*.xml', (err, files) => {

调用glob不返回 a Promise,因此await本质上是无用的。因此,您需要自己创建承诺。

exports.checkFileDrop = async () => {
  console.log('Checking for xml in filedrop...');

  const files = await new Promise((resolve, reject) => glob('./filedrop/ALLREQUESTS-*.xml', (err, files) => {
    if (err) reject(err);
    else resolve(files);
  });

  const parser = new xml2js.Parser();

  const data = await new Promise((resolve, reject) => fs.readFile('./filedrop/ALLREQUESTS-20170707.xml', 'utf16le', function (err, data) {
    if (err) reject(err);
    else resolve(data);
  });

  const result = await new Promise((resolve, reject) => parser.parseString(data, (err, result) => {
    if (err) reject(err);
    else resolve(result);
  });

  console.log('data found');

  const requests = JSON.stringify(result.Records.Record);

  console.log(requests);
}

请注意,现在此函数将拒绝它返回的承诺,而不是强制记录错误。

您也可以使用助手将其压缩。例如,Node 8 包含util.promisify以使这样的代码更易于编写,例如

const util = require('util');

exports.checkFileDrop = async () => {
  console.log('Checking for xml in filedrop...');

  const files = await util.promisify(glob)('./filedrop/ALLREQUESTS-*.xml');
  const parser = new xml2js.Parser();

  const data = await util.promisify(fs.readFile)('./filedrop/ALLREQUESTS-20170707.xml', 'utf16le');

  const result = await util.promisify(parser.parseString.bind(parser))(data);

  console.log('data found');

  const requests = JSON.stringify(result.Records.Record);

  console.log(requests);
}
于 2017-07-26T17:12:15.207 回答
0

您可以使用异步/等待

import fs from 'fs';
import { promisify } from 'util';

const xmlToJson = async filePath => {
  const parser = new xml2js.Parser
  try {
    const data = await fs.promises.readFile(filePath, 'utf8')
    const result = await promisify(parser.parseString)(data);
    const requests = JSON.stringify(result.merchandiser.product);
    return requests
  }
  catch(err) {
    console.log(err)
  }
}
于 2020-04-18T03:49:12.407 回答