Проблема с fs.writeFile в уменьшении с получением - PullRequest
0 голосов
/ 17 января 2020

Мне нужна помощь с этим помощником, которого я пишу. По какой-то причине, используя сокращение в asyn c в readFile, при попытке записать результаты в файл он не перейдет к следующему элементу массива. Однако, если я использую console.log, он работает просто отлично.

const neatCsv = require('neat-csv');
const fetch = require('node-fetch');
const fs = require('fs');

fs.readFile('./codes.csv', async (err, data) => {
    if (err) { throw err; }

    let baseUrl = 'https://hostname/orders?from=2019-10-21T00:00:00.001Z&to=2019-12-31T23:59:59.000Z&promo=';
    const starterPromise = Promise.resolve(null);
    const promos = await neatCsv(data);
    const logger = (item, result) => console.log(item, result);

    function write (item, result) {
        return new Promise((resolve, reject) => {
            fs.writeFile(`./output/${item.PROMO}.json`, JSON.stringify(result), (err) => {
                if (err) { throw err; }
                console.log(`Wrote file ${item.PROMO}`);
            });
        })
    }

    function asyncFetch(item) {
        console.log(`runTask <---------${item.PROMO}---------`);
        return fetch(`${baseUrl}${item.PROMO}`, { headers: { 'x-apikey': 'xyz' }})
            .then(res => (res.json())
            .then(json => json))
    }

    await promos.reduce(
        (p, item) => p.then(() => asyncFetch(item).then(result => write(item, result))),
        starterPromise
    )
});

CSV-файл - это просто базовый c макет, подобный такому.

PROMO
12345
56789
98765
...

Цель состоит в том, чтобы перебрать их, выполнить вызов REST, чтобы получить результаты json, и записать их в файл с именем текущего промо, а затем перейти к следующему, сделать новый вызов и сохранить его в другом файле с соответствующий код.

В редукте, если вы вызываете logger вместо write, он работает нормально. При вызове write он просто делает один и тот же вызов снова и снова и перезаписывает один и тот же файл, заставляя меня убить его. Пожалуйста, помогите, я схожу с ума здесь ...

1 Ответ

1 голос
/ 17 января 2020

Вы могли бы лучше использовать повсеместно функции async, API обещаний fs и простое время l oop для потребления элементов CSV. Dry, естественно, поскольку у меня нет вашего CSV или API.

(Ваша первоначальная проблема, вероятно, связана с тем, что вы не resolve / reject в write функция, но уменьшать ад тоже не нужно ...)

const neatCsv = require("neat-csv");
const fetch = require("node-fetch");
const fsp = require("fs").promises;

const logger = (item, result) => console.log(item, result);

const baseUrl = "https://hostname/orders?from=2019-10-21T00:00:00.001Z&to=2019-12-31T23:59:59.000Z&promo=";

async function asyncFetch(item) {
  console.log(`runTask <---------${item.PROMO}---------`);
  const res = await fetch(`${baseUrl}${item.PROMO}`, { headers: { "x-apikey": "xyz" } });
  const json = await res.json();
  return json;
}

async function write(item, result) {
  await fsp.writeFile(`./output/${item.PROMO}.json`, JSON.stringify(result));
  console.log(`Wrote file ${item.PROMO}`);
}

async function process() {
  const data = await fsp.readFile("./codes.csv");
  const promos = await neatCsv(data);
  while (promos.length) {
    const item = promos.shift();
    const result = await asyncFetch(item);
    await write(item, result);
  }
}

process().then(() => {
  console.log("done!");
});

Версия, которая использует фиктивные данные и сервис JSON Placeholder, работает просто отлично:

const fetch = require("node-fetch");
const fsp = require("fs").promises;

const baseUrl = "https://jsonplaceholder.typicode.com/comments/";

async function asyncFetch(item) {
  console.log(`runTask <---------${item.PROMO}---------`);
  const res = await fetch(`${baseUrl}${item.PROMO}`);
  return await res.json();
}

async function write(item, result) {
  const data = JSON.stringify(result);
  await fsp.writeFile(`./output/${item.PROMO}.json`, data);
  console.log(`Wrote file ${item.PROMO}: ${data}`);
}

async function getItemList() {
  return [
    {PROMO: '193'},
    {PROMO: '197'},
    {PROMO: '256'},
   ];
}

async function process() {
  const promos = await getItemList();
  while (promos.length) {
    const item = promos.shift();
    const result = await asyncFetch(item);
    await write(item, result);
  }
}

process().then(() => {
  console.log("done!");
});
...