【问题标题】:Returning parsed JSON array asynchronously异步返回解析的 JSON 数组
【发布时间】:2020-08-07 10:46:21
【问题描述】:

我正在尝试解析示例 JSON 并将各个对象推送到数组中。我遇到的问题是我认为它正在工作,但是当调用console.log 打印结果时,它返回一个undefined 值。我相信这是因为我没有正确处理我的 async/await 请求,但我不确定在所有元素都被推送到我的数组之前如何不运行 console.log 函数。

Attacks.js

//Assume JSON output = {attack source, attack destination, attack type}

//Required modules
//@ts-ignore: undeclared module
//const watchStream = require('fs-watch-stream')
const es = require('event-stream')
var JSONStream = require('JSONStream')
const fs = require('fs');


async function initial(){
    var arr = [];
    var stream = fs.createReadStream('sample.json', {start: 3, encoding: 'utf8'});
    var parser = JSONStream.parse('employees.employee.*');
    stream.pipe(parser);

    parser.on('data', function (obj) {
        arr.push(obj);
    });

    parser.on('finish', async function(arr) {
        return(arr) = await Promise.resolve(arr);
    });
};

initial().then(arr => console.log(arr));

sample.json

{
  "employees": {
    "employee": [
      {
        "id": "1",
        "firstName": "Tom",
        "lastName": "Cruise",
        "photo": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "id": "2",
        "firstName": "Maria",
        "lastName": "Sharapova",
        "photo": "https://jsonformatter.org/img/Maria-Sharapova.jpg"
      },
      {
        "id": "3",
        "firstName": "Robert",
        "lastName": "Downey Jr.",
        "photo": "https://jsonformatter.org/img/Robert-Downey-Jr.jpg"
      }
    ]
  }
}

【问题讨论】:

  • 我不认为 async 和 .then() 混合。 “让 arr = await initial()”有效吗?
  • 您可以在代码本身中编写console.log() 语句。前任。 parser.on('data', function (obj) { arr.push(obj); }); 下一行可以是console.log(arr)
  • @DevOfZot 代替哪一行?
  • @zer00ne 这样做时,它会在每次读取一条数据时打印数组。这导致打印 3 个不同的数组,每个数组都比下一个长。我只想打印最终结果。

标签: javascript json promise async-await


【解决方案1】:

下面的代码简单地定义了一个事件处理程序;你的 initial 函数甚至不会等待委托执行,更不用说完成了:

parser.on('finish', async function(arr) {
    return(arr) = await Promise.resolve(arr);
});

您应该将处理程序包装在Promise 中,initial 可以等待:

await Promise(resolve => parser.on("finish", resolve));

【讨论】:

    【解决方案2】:

    问题出在这部分:

    parser.on('finish', async function(arr) {
      return(arr) = await Promise.resolve(arr);
    });
    

    finish事件被触发时,回调函数function(arr)被调用,但是因为它是一个函数,所以它里面的任何return语句都不会被initial()返回,而是被function(arr)返回并且没有分配任何变量,因此return(arr) 中返回的值丢失了。您期望 initial() 解析为 arr 但由于 return arr 语句已经在 function(arr) 内部,因此返回值丢失,并且因为 initial 最终没有任何 return 语句它解析到undefined。我认为在这种情况下,更简单的方法是使用经典的承诺流程。

    function initial(){
       return new Promise(resolve => {
          var arr = [];
          var stream = fs.createReadStream('sample.json', {start: 3, encoding: 'utf8'});
          var parser = JSONStream.parse('employees.employee.*');
          stream.pipe(parser);
    
          parser.on('data', function (obj) {
            arr.push(obj);
          });
    
          parser.on('finish', function(arr) {
            resolve(arr);
          });
       }) 
    };
    
    initial().then(arr => console.log(arr));
    

    【讨论】:

    • JS 代码编译没有错误,但是我根本没有得到任何输出。也许数组没有正确返回?
    • 那是因为代码没有任何问题,只是你的函数没有做你需要它做的事情。正如你所说的数组没有正确返回我更新了我的答案,希望能更清楚
    • 我明白了,我一定不能正确地推/管道到阵列。
    • 只是提醒一下,我想通了。在我的parser.on('finish', function(arr) { 行中,删除arr 代替空白括号。我猜arr 已经定义好了,所以再次传入arr 会导致我丢失这些值。欣赏提示。
    猜你喜欢
    • 2018-08-12
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 2013-04-05
    • 2020-12-25
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    相关资源
    最近更新 更多