我一直在使用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文件。該文件包含用於獲取頁面的網址。現在,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(),數據將無法混合起來。任何想法爲什麼發生這種情況?
謝謝,我不敢相信我之前沒有注意到這個問題。我在解析的變量之前添加了let。但是這並沒有解決這個問題。 – Pegladon