【问题标题】:Read csv asynchronous - NodeJS异步读取 csv - NodeJS
【发布时间】:2021-03-10 02:13:22
【问题描述】:

我正在循环一个数组并从一个 CSV 文件中读取数据,这样我就可以减少它的数据,我已经实现了这样的东西。我想从内存中的 csv 文件填充 Map 变量并从中获取数据。但我想填充一次(或者当我明确这样做时,但那是另一回事)。

运行时我想这样打印:

before 
after

但我明白了:

before
before
before
after
after
after

显然当从 CSV 读取时没有等待。有什么方法可以从 CSV 异步读取?

这是我的代码:

let myMap = new Map();
const parseMap = async(stream) => {
    const map = new Map();
    return new Promise((resolve, reject) => {
        stream
           .on('data', elems => {
              const key = elems[0];
              const value = elems.slice(-1)[0];
              map.set(key, value);
           })
           .on('error', () => reject)
           .on('end', () => {
             console.log('promise');
             resolve(map);
        });
  });  
}

const getMap = async(path_string) => {
    const stream = fs.createReadStream(path_string).pipe(parse({delimiter: DELIMITER}));
    return await parseMap(stream);
    
}
const translate = async (key) => {
    if (!myMap.size) {
        console.log('before');
        myMap = await getMap('my-csv.csv');
        console.log('after');
    }
    return myMap.get(key);
};

const guidRankings = await ['a', 'b', 'c'].reduce(async (accumulator, value, idx) => {
        const data = await translate(value);
        if (data) {
            (await accumulator).push({
                data,
                order: idx
            });
        }
        return accumulator;
    }, Promise.resolve([]));

【问题讨论】:

    标签: javascript arrays csv async-await


    【解决方案1】:

    reduce 方法无法处理异步回调。

    您需要向它传递一个返回您关心的实际值的函数,而不是返回一个承诺的函数。

    1. map你的数组值通过translate得到一个promise数组
    2. 使用await Promise.all 等待它们全部解决并获取已翻译值的数组
    3. reduce 那个数组(没有在 reducer 内做任何异步操作)。

    【讨论】:

    • 是的,我用地图试过了,我得到了同样的结果。问题是读取 csv 时不会等待
    • 你想让它等待什么?您正在翻译 3 件事,因此 translate 函数将运行 3 次并在 3 次之前和之后记录,这应该不是问题。
    • 正确,翻译函数被调用了 3 次,但是它有一个 if 语句,只有当 myMap 映射中没有数据时才会 getMap(从 csv 文件中读取),所以这个应该只在第一次迭代中发生
    • ifconsole.log 语句触发的次数无关,如果您按照我所说的操作并且不要尝试在减速器中执行任何异步操作,则应该解决此问题。
    • const 结果 = await Promise.all(['a', 'b', 'c'].map(async (i,order) => { const id = await translate(i);返回 { id, order }; }));
    【解决方案2】:

    假设可以同时进行 3 个调用,它只是使用 map 来存储 promise,使用 Promise All 等待它们完成,然后使用 map 来获取您的数组。

    const promises = ['a', 'b', 'c'].map(value) => translate(value));
    const results = await Promise.all(promises);
    const guidRankings = results.map((data, order) => ({ data, order }));
    

    如果由于某种原因必须一次制作一个,您想使用for await of

    【讨论】:

      猜你喜欢
      • 2019-01-13
      • 1970-01-01
      • 2021-02-07
      • 2014-10-11
      • 2021-11-07
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      相关资源
      最近更新 更多