gpt4 book ai didi

javascript - 循环写入文件 - JS

转载 作者:行者123 更新时间:2023-12-01 02:27:10 26 4
gpt4 key购买 nike

尝试在循环中写入文件时似乎遇到问题,即使第一个文件尚未创建,循环仍在迭代(我认为我要么不理解 promise ,要么不理解脚本的异步性质)

因此,我将在命令行上运行node write_file_script.js prime_league

// teams.js
module.exports = {
premier_league: [
{ team_name: "Team 1", friendly_name: "name 1"},
{ team_name: "Team 2", friendly_name: "name 2"}
]
}

我的脚本

const args = process.argv.slice(2);
const TEAM = require('./teams');

const Excel = require('exceljs');
const workbook = new Excel.Workbook();

for (var team = 0; team < TEAM[args].length; team++) {
console.log("Starting Excel File generation for " + TEAM[args][team]['team_name']);
var fhcw = require('../data_files/home/fhcw/' + TEAM[args][team]['friendly_name'] + '_home' + '.json');
fhcw = fhcw.map(Number);

workbook.xlsx.readFile('./excel_files/blank.xlsx')
.then(function() {
var worksheet = workbook.getWorksheet(1);
// Write FHCW
for (i=0; i < fhcw.length; i++) {
col = i+6;
worksheet.getCell('E'+ col).value = fhcw[i];
}

console.log(TEAM[args][team])
workbook.xlsx.writeFile('./excel_files/' + TEAM[args] + '/' + TEAM[args][team]['friendly_name'] + '.xlsx');

});

}

运行时得到的输出是

Starting Excel File generation for Team 1
Starting Excel File generation for Team 2
undefined
(node:75393) UnhandledPromiseRejectionWarning: Unhandled promise rejection
(rejection id: 1): TypeError: Cannot read property 'friendly_name' of undefined

所以看起来文件没有被写入但循环仍在继续,我如何确保在进入下一个循环之前文件已被写入?

谢谢

最佳答案

如果函数返回一个Promise,并且您想要串行执行它们(一次一个)而不是并行执行(同时开始所有操作),则需要等待在开始下一个之前使用 then()

另外,请注意,您的 TEAM 只是一个数组的导出(至少如所呈现的那样),因此您不能给它 args,这是其他错误来自。

当您有一系列要做的事情时,最好的方法是建立一个队列,运行该队列直到文件用完。在这种情况下,您的 TEAM 数组看起来像是您的队列,但由于这是一个导出,我建议不一定要更改它,而是将其复制到您可以更改的另一个数组:

const args = process.argv.slice(2);
const TEAM = require('./teams');

const Excel = require('exceljs');
const workbook = new Excel.Workbook();

const writeNextFile = (queue) => {
// If we have nothing left in the queue, we're done.
if (!queue.length) {
return Promise.resolve();
}

const team = queue.shift(); // get the first element, take it out of the array

console.log("Starting Excel File generation for " + team.team_name);
var fhcw = require('../data_files/home/fhcw/' + team.friendly_name + '_home' + '.json');
fhcw = fhcw.map(Number);

// return this promise chain
return workbook.xlsx.readFile('./excel_files/blank.xlsx')
.then(function() {
var worksheet = workbook.getWorksheet(1);
// Write FHCW
for (i=0; i < fhcw.length; i++) {
col = i+6;
worksheet.getCell('E'+ col).value = fhcw[i];
}

console.log(team);
// not sure what you thought this would TEAM[args] would have translated to, but it wouldn't have been a string, so I put ??? for now
// also, making the assumption that writeFile() returns a Promise.
return workbook.xlsx.writeFile('./excel_files/' + team.??? + '/' + team.friendly_name + '.xlsx');
}).then(() => writeNextFile(queue));
}

writeNextFile(TEAM.slice(0)) // make a copy of TEAM so we can alter it
.then(() => console.log('Done'))
.catch(err => console.error('There was an error', err));

基本上,我们的函数采用一个数组并写入第一个团队,然后递归调用自身来调用下一个团队。最终一切都会解决,你最终会得到一个最终解决的 Promise。

当涉及到 Promise 时,您基本上总是需要将它们链接在一起。您将无法对它们使用 for 循环,或任何其他标准循环。

如果您想一次编写所有它们,它会更干净一些,因为您可以为每个文件做一个非递归映射,并使用 Promise.all 来知道它们何时完成。

const writeNextFile = (team) => {
console.log("Starting Excel File generation for " + team.team_name);
var fhcw = require('../data_files/home/fhcw/' + team.friendly_name + '_home' + '.json');
fhcw = fhcw.map(Number);

// return this promise chain
return workbook.xlsx.readFile('./excel_files/blank.xlsx')
.then(function() {
var worksheet = workbook.getWorksheet(1);
// Write FHCW
for (i=0; i < fhcw.length; i++) {
col = i+6;
worksheet.getCell('E'+ col).value = fhcw[i];
}

console.log(team);
// not sure what you thought this would TEAM[args] would have translated to, but it wouldn't have been a string, so I put ??? for now
// also, making the assumption that writeFile() returns a Promise.
return workbook.xlsx.writeFile('./excel_files/' + team.??? + '/' + team.friendly_name + '.xlsx');
});
}

Promise.all(TEAM.map(writeTeamFile))
.then(() => console.log('Done')
.catch(err => console.error('Error'));

Promise 用于异步,通常当您有一组事情时,您希望并行执行它们,因为这样更快。这就是为什么并行版本要干净得多;我们不必递归地调用事物。

关于javascript - 循环写入文件 - JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48661491/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com