Данные из одного асинхронного выполнения функции смешиваются с другим выполнением функции

Я писал API веб-скрепинга, построенный на основе NodeJS, используя Cheerio, node-fetch и fs-extra. В следующем фрагменте кода я вызываю метод getReport для каждой строки в массиве config.supportedMountains. Для каждого из элементов я хочу запустить их через функцию fetchAndStore, которая делает запрос html, запускает его через определенный анализатор и затем сохраняет результаты json.

// const fs = require('fs-extra');
const _ = require('lodash');
// const Promise = require('promise');
const schedule = require('node-schedule');

const fetchAndStore = require('./fetchAndStore.js');

const config = require('../config.js');

exports.run = function() {
  schedule.scheduleJob('*/20 * * * * *', function() {
    // Get the most recent reports
    // And write them to storage
    _.forEach(config.supportedMountains, function(fName) {
      getReport(fName);
    });
  });
};

/**
 * Gets the lift statuses for every mountain
 * @param {string} fName the file name of the mountain
 * @return {promise} the promise resolved when the file is written
 */
function getReport(fName) {
  return fetchAndStore.run(fName);
}

Здесь вы можете увидеть файл загрузки и сохранения. Этот файл принимает имя fName и требует соответствующий файл staticData. Этот файл содержит URL для загрузки страницы. Теперь выполняется html-запрос, и он запускается через анализатор. Затем с полученным проанализированным json проходит несколько шагов для его сохранения. Окончательный вывод должен состоять из двух файлов, один из которых хранит отчеты, а другой - исторический снегопад, большая часть логики в функциях fs.outputJson заключается в обработке отсутствующих файлов.

const fs = require('fs-extra');
const fetch = require('node-fetch');

exports.run = (function(fName) {
  // Get the staticJson
  let staticJson = require(`../staticData/mountains/${fName}.json`);
  // console.log(staticJson.id)

  // Output the report
  return fetch(staticJson.urls.reportFetchUrl).then(function(res) {
    return res.text();
  }).then(function(html) {
    // Run the html through the parser
    let parser = require(`../scrapers/${staticJson.sName}.js`);
    parsed = parser.run(html);
    // Output the report
    return fs.outputJson(
      `data/reports/${staticJson.id}.json`,
      parsed.report
    ).then(function() {
      // console.log(parsed.report.lifts[0].name);
      // Once output is completed
      if (parsed.snowHistory) {
        // If snow history is defined
        // Read the old file
        return fs.readJson(
          `data/snowHistory/${staticJson.id}.json`
        ).then(function(oldJson) {
          // If the date of the old json is todays date
          if (oldJson[0].date === parsed.snowHistory.date) {
            // Replace the first element in array
            oldJson[0] = parsed.snowHistory;
            return fs.outputJson(
              `data/snowHistory/${staticJson.id}.json`,
              oldJson
            );
          } else {
            // If this is a fresh entry
            oldJson.unshift(parsed.snowHistory);
            // If the record does not exist
            return fs.outputJson(
              `data/snowHistory/${staticJson.id}.json`,
              oldJson
            );
          }
        }).catch(function(e) {
          // If the old file cannot be read
          if (e.code === 'ENOENT') {
            // If the file does not exist
            // Write brand new file
            return fs.outputJson(
              `data/snowHistory/${staticJson.id}.json`,
              [parsed.snowHistory]
            );
          }
        });
      }
    });
  });
});

По какой-то причине, когда работает скребок, примерно в 1/4 времени данные из одного выполнения fetchAndStore будут смешиваться с данными из другого выполнения fetchAndStore, что означает, что в файловую систему будут записаны неправильные данные. Как это возможно? Я подумал, что, поскольку я делаю вызовы fetchAndStore.run() отдельно, данные не могут быть перепутаны. Есть идеи, почему это происходит?

1 ответ

Первое, что я вижу, это то, что parsed глобально ограничен. Может ли это быть проблемой? Кроме того, если вы вкладываете это глубоко, вы действительно должны рассмотреть возможность разбить это на несколько функций.

Другие вопросы по тегам