NodeJS队列多个execFile调用
NodeJS Queue multiple execFile calls
我正在制作一个基于 Web 的工具,它可以挂接到一个名为 RetroPie-Setup 的现有 shell 框架中。
他们有一个名为 /RetroPie-Setup/retropie_packages.sh 的 shell 脚本,您可以使用它来安装、获取依赖项,甚至编译不同的程序。
一个问题是 packages.sh 不应该在给定时刻多次 运行,所以我需要设置一个 运行 一次一个的队列。
我想我可以使用 promise-queue 来防止多次执行,但是每当我 运行 execFile 时,它都会立即 运行 执行命令而不是当它到达某个位置时在队列中。
这是我的示例代码:
downloadTest.sh
(下载具有唯一名称的 10Mb 文件):
filename=test$(date +%H%M%S).db
wget -O ${filename} speedtest.ftp.otenet.gr/files/test10Mb.db
rm ${filename}
节点代码:
const Queue = require('promise-queue')
const { spawn,execFile } = require('child_process');
var maxConcurrent = 1;
var maxQueue = Infinity;
var que = new Queue(maxConcurrent, maxQueue);
var testFunct = function(file)
{
var promise = new Promise((reject,resolve) => {
execFile(file,function(error, stdout, stderr) {
console.log('Finished executing');
if(error)
{
reject();
} else
{
resolve(stdout);
}
});
})
return promise;
}
var test1 = testFunct('/home/pi/downloadTest.sh')
var test2 = testFunct('/home/pi/downloadTest.sh')
var test3 = testFunct('/home/pi/downloadTest.sh')
que.add(test1);
que.add(test2);
que.add(test3);
您的代码非常接近工作。主要问题是你正在执行 testFunct()
,这又 returns 一个立即开始执行其中内容的 Promise。为了解决这个问题,可以使用 Function.prototype.bind()
将参数绑定到函数而不执行它。像这样:
que.add(testFunct.bind(null, '/home/pi/downloadTest.sh'));
que.add(testFunct.bind(null, '/home/pi/downloadTest.sh'));
que.add(testFunct.bind(null, '/home/pi/downloadTest.sh'));
或者您可以使用 async/await
,这使得队列的实现变得微不足道,这反过来又允许您放弃对 promise-queue
.
的依赖
const execFile = require("util").promisify(require("child_process").execFile)
(async function () {
let scripts = [
"/home/pi/downloadTest.sh",
"/home/pi/downloadTest.sh",
"/home/pi/downloadTest.sh"
]
for (let script of scripts) {
try {
let { stdout, stderr } = await execFile(script)
console.log("successfully executed script:", script)
} catch (e) {
// An error occured attempting to execute the script
}
}
})()
上面代码中有趣的部分是await execFile(script)
。当您 await
一个表达式时,整个函数的执行将暂停,直到 execFile
函数返回的 Promise 解析或拒绝,这意味着您有一个按顺序执行的队列。
我正在制作一个基于 Web 的工具,它可以挂接到一个名为 RetroPie-Setup 的现有 shell 框架中。
他们有一个名为 /RetroPie-Setup/retropie_packages.sh 的 shell 脚本,您可以使用它来安装、获取依赖项,甚至编译不同的程序。
一个问题是 packages.sh 不应该在给定时刻多次 运行,所以我需要设置一个 运行 一次一个的队列。
我想我可以使用 promise-queue 来防止多次执行,但是每当我 运行 execFile 时,它都会立即 运行 执行命令而不是当它到达某个位置时在队列中。
这是我的示例代码:
downloadTest.sh
(下载具有唯一名称的 10Mb 文件):
filename=test$(date +%H%M%S).db
wget -O ${filename} speedtest.ftp.otenet.gr/files/test10Mb.db
rm ${filename}
节点代码:
const Queue = require('promise-queue')
const { spawn,execFile } = require('child_process');
var maxConcurrent = 1;
var maxQueue = Infinity;
var que = new Queue(maxConcurrent, maxQueue);
var testFunct = function(file)
{
var promise = new Promise((reject,resolve) => {
execFile(file,function(error, stdout, stderr) {
console.log('Finished executing');
if(error)
{
reject();
} else
{
resolve(stdout);
}
});
})
return promise;
}
var test1 = testFunct('/home/pi/downloadTest.sh')
var test2 = testFunct('/home/pi/downloadTest.sh')
var test3 = testFunct('/home/pi/downloadTest.sh')
que.add(test1);
que.add(test2);
que.add(test3);
您的代码非常接近工作。主要问题是你正在执行 testFunct()
,这又 returns 一个立即开始执行其中内容的 Promise。为了解决这个问题,可以使用 Function.prototype.bind()
将参数绑定到函数而不执行它。像这样:
que.add(testFunct.bind(null, '/home/pi/downloadTest.sh'));
que.add(testFunct.bind(null, '/home/pi/downloadTest.sh'));
que.add(testFunct.bind(null, '/home/pi/downloadTest.sh'));
或者您可以使用 async/await
,这使得队列的实现变得微不足道,这反过来又允许您放弃对 promise-queue
.
const execFile = require("util").promisify(require("child_process").execFile)
(async function () {
let scripts = [
"/home/pi/downloadTest.sh",
"/home/pi/downloadTest.sh",
"/home/pi/downloadTest.sh"
]
for (let script of scripts) {
try {
let { stdout, stderr } = await execFile(script)
console.log("successfully executed script:", script)
} catch (e) {
// An error occured attempting to execute the script
}
}
})()
上面代码中有趣的部分是await execFile(script)
。当您 await
一个表达式时,整个函数的执行将暂停,直到 execFile
函数返回的 Promise 解析或拒绝,这意味着您有一个按顺序执行的队列。