2017-08-31 15 views
2

Cheerio、node-fetch、およびfs-extraを使用してNodeJSの上に構築されたWebスクレイピングAPIを作成しました。次のコードでは、config.supportedMountains配列の各文字列に対してgetReportメソッドを呼び出します。それぞれの項目について、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を使用して、これを保存するためのいくつかのステップが実行されます。最終的な出力は、2つのファイルでなければなりません.1つはレポートを格納し、もう1つはhistoricalSnowfallを格納します.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()を別々に呼び出しているので、データが混ざり合うことはないと考えました。なぜこれが起こっているのか?

答えて

0

まず、parsedがグローバルスコープであることがわかります。それが問題だろうか?さて、あなたが深く入れ子にしているなら、あなたは実際にこれをいくつかの機能で分割することを検討すべきです。

+0

ありがとう、私はこの問題を以前に気付かなかったとは思えません。私は、解析された変数の前にletを追加しました。しかし、これは問題を解決しませんでした。 – Pegladon

関連する問題