Node JS с ax ios async / await: записать ответ в локальный файл - PullRequest
0 голосов
/ 02 августа 2020

Я разрабатываю приложение Node CLI для локального использования. Он принимает CSV-файл в качестве входных данных и на основе значений в его столбце userId делает запрос GET к API, используя одно из этих значений за раз в качестве входных. Ниже я создал фиктивный пример этого. Вот запрос ax ios, завернутый в функцию asyn c, которая возвращает Promise:

const axios = require("axios");
const utils = require("./utils");
const fs = require("fs").promises;

async function getTitleGivenId(id) {
  try {
    return await axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`);
  } catch (error) {
    console.error(error);
  }
}

// This works fine
getTitleGivenId(1).then(res => {
  console.log(res.data.title);
});

Я придумал это, чтобы написать CSV, но allData строка не обновляется внутри функции map:

async function saveTitles(inCsv, outCsv) {
  try {
    const arrOfObj = utils.readCsv(inCsv);
    // [
    //   { userId: '1', color: 'green' },
    //   { userId: '2', color: 'blue' },
    //   { userId: '3', color: 'red' }
    // ]

    let allData = "color,title\n";
    arrOfObj.map(o => {
      let title;
      getTitleGivenId(o["userId"]).then(res => {
        title = res.data.title;
        allData += `${o["color"]},${title}\n`;
      });
    });
    await fs.writeFile(outCsv, allData);
  } catch (err) {
    console.error(err);
  }
}

// This writes only "color,title" to "outCsv.csv"
saveTitles("./inputCsv.csv", "./outCsv.csv");

Мы будем очень благодарны за любые предложения / альтернативные способы продолжения.

1 Ответ

1 голос
/ 02 августа 2020

Он обновляется. Вы просто не ждете, когда это закончится. Функция map() выполняется, но она не будет ждать завершения внутренних обещаний. Таким образом, один из вариантов - сделать также функцию карты async и просто дождаться завершения всех итераций:

let allData = "color,title\n";
await Promise.all( arrOfObj.map( async (o) => {
  const res = await getTitleGivenId(o["userId"])
  const title = res.data.title;
  allData += `${o["color"]},${title}\n`;
}) );
await fs.writeFile(outCsv, allData);
...