NodeJS - 按数组中每个元素之间的超时顺序循环遍历数组
NodeJS - Looping through Array Sequentially with Timeout between each Element in Array
我有一个数组中的命令列表,我需要按顺序 运行:
const commands = [
`git clone https://github.com/EliLillyCo/${repo}.git`,
`cd ${repo}`, `git checkout -b ${branch}`,
'cp ../codeql-analysis.yml .github/workflows/',
'git add .github/workflows/codeql-analysis.yml',
`git push --set-upstream origin ${branch}`,
'cd ../',
`rm -r ${repo}`,
];
他们需要才能运行,因为命令依赖于之前的命令运行。
此外,每个命令在运行执行下一个命令之前需要等待 3 秒,因为有时命令需要时间,尤其是命令 1 和命令 5.
我正在使用标准 for
循环,然后使用 setTimeout()
调用一个函数来 运行 命令,例如:
const a = require('debug')('worker:sucess');
const b = require('debug')('worker:error');
const { exec } = require('child_process');
function execCommand(command) {
exec(command, (error, stdout, stderr) => {
if (error) {
b(`exec error: ${error}`);
return;
}
a(`stdout: ${stdout}`);
b(`stderr: ${stderr}`);
});
}
const commands = [
`git clone https://github.com/EliLillyCo/${repo}.git`,
`cd ${repo}`, `git checkout -b ${branch}`,
'cp ../codeql-analysis.yml .github/workflows/',
'git add .github/workflows/codeql-analysis.yml',
`git push --set-upstream origin ${branch}`,
'cd ../',
`rm -r ${repo}`,
];
for (let i = 0; i < commands.length; i++) {
setTimeout(execCommand(commands[i]), 3000);
}
但是 setTimeout()
有问题,因为它返回这个:
worker:error TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined
在使用超时的同时解决顺序循环数组问题的最佳方法是什么?
我会做出 execCommand
return 的承诺,这样你就知道什么时候完成了;你不能依赖超时(如果任务需要超过三秒怎么办?)并且由于大多数这些命令将完成 much 比这快得多,超时会不必要地阻止事情。
这是execCommand
return一个承诺:
function execCommand(command) {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
b(`exec error: ${error}`);
reject(error);
return;
}
a(`stdout: ${stdout}`);
b(`stderr: ${stderr}`);
resolve();
});
});
}
然后,如果您有可用的顶级 await
(现代 Node.js 和 ESM 模块):
// If you have top-level `await` available
try {
for (const commmand of commands) {
await execCommand(command);
}
} catch (error) {
// ...report/handle error...
}
如果不这样做,请将其包装在 async
IIFE 中:
(async () => {
for (const commmand of commands) {
await execCommand(command);
}
})().catch(error => {
// ...report/handle error...
});
或者,如果您想将执行与 stdout
/stderr
的处理分开,您可以直接在 exec
上使用 util.promisify
,但将它们一起执行是对你所拥有的东西的最小改变,所以这就是我坚持的。
目前您不能保证调用下一个命令时上一个命令将完成。您在 3000 毫秒后自动调用下一个,但上一个可能需要比预期更长的时间并且尚未结束。
您应该添加一种机制来等待每个命令,然后启动下一个命令。下面是如何使用 async/await
:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const commands = [ ... ];
const execCommand = async (command) => {
try {
await exec(command)
} catch (error) {
b(`exec error: ${error}`);
return;
}
a(`stdout: ${stdout}`);
b(`stderr: ${stderr}`);
}
(async () => {
for (let command of commands) {
await execCommand(command);
}
})();
我有一个数组中的命令列表,我需要按顺序 运行:
const commands = [
`git clone https://github.com/EliLillyCo/${repo}.git`,
`cd ${repo}`, `git checkout -b ${branch}`,
'cp ../codeql-analysis.yml .github/workflows/',
'git add .github/workflows/codeql-analysis.yml',
`git push --set-upstream origin ${branch}`,
'cd ../',
`rm -r ${repo}`,
];
他们需要才能运行,因为命令依赖于之前的命令运行。
此外,每个命令在运行执行下一个命令之前需要等待 3 秒,因为有时命令需要时间,尤其是命令 1 和命令 5.
我正在使用标准 for
循环,然后使用 setTimeout()
调用一个函数来 运行 命令,例如:
const a = require('debug')('worker:sucess');
const b = require('debug')('worker:error');
const { exec } = require('child_process');
function execCommand(command) {
exec(command, (error, stdout, stderr) => {
if (error) {
b(`exec error: ${error}`);
return;
}
a(`stdout: ${stdout}`);
b(`stderr: ${stderr}`);
});
}
const commands = [
`git clone https://github.com/EliLillyCo/${repo}.git`,
`cd ${repo}`, `git checkout -b ${branch}`,
'cp ../codeql-analysis.yml .github/workflows/',
'git add .github/workflows/codeql-analysis.yml',
`git push --set-upstream origin ${branch}`,
'cd ../',
`rm -r ${repo}`,
];
for (let i = 0; i < commands.length; i++) {
setTimeout(execCommand(commands[i]), 3000);
}
但是 setTimeout()
有问题,因为它返回这个:
worker:error TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined
在使用超时的同时解决顺序循环数组问题的最佳方法是什么?
我会做出 execCommand
return 的承诺,这样你就知道什么时候完成了;你不能依赖超时(如果任务需要超过三秒怎么办?)并且由于大多数这些命令将完成 much 比这快得多,超时会不必要地阻止事情。
这是execCommand
return一个承诺:
function execCommand(command) {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
b(`exec error: ${error}`);
reject(error);
return;
}
a(`stdout: ${stdout}`);
b(`stderr: ${stderr}`);
resolve();
});
});
}
然后,如果您有可用的顶级 await
(现代 Node.js 和 ESM 模块):
// If you have top-level `await` available
try {
for (const commmand of commands) {
await execCommand(command);
}
} catch (error) {
// ...report/handle error...
}
如果不这样做,请将其包装在 async
IIFE 中:
(async () => {
for (const commmand of commands) {
await execCommand(command);
}
})().catch(error => {
// ...report/handle error...
});
或者,如果您想将执行与 stdout
/stderr
的处理分开,您可以直接在 exec
上使用 util.promisify
,但将它们一起执行是对你所拥有的东西的最小改变,所以这就是我坚持的。
目前您不能保证调用下一个命令时上一个命令将完成。您在 3000 毫秒后自动调用下一个,但上一个可能需要比预期更长的时间并且尚未结束。
您应该添加一种机制来等待每个命令,然后启动下一个命令。下面是如何使用 async/await
:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const commands = [ ... ];
const execCommand = async (command) => {
try {
await exec(command)
} catch (error) {
b(`exec error: ${error}`);
return;
}
a(`stdout: ${stdout}`);
b(`stderr: ${stderr}`);
}
(async () => {
for (let command of commands) {
await execCommand(command);
}
})();