gpt4 book ai didi

javascript - 在 shell 执行期间无法使用 socket.io 发出当前服务器状态

转载 作者:行者123 更新时间:2023-12-02 23:05:45 25 4
gpt4 key购买 nike

我想执行 shell 构建脚本并将当前执行状态发送给 Angular 客户端。问题是,emit 不会在调用后立即执行。程序等待完成整个函数,然后将所有发出的信号一起发送。

const express = require('express');
const app = express();
const socketIO = require('socket.io');
const execSync = require('child_process').execSync;

[...]

app.post('/bootupserver', function(req, res) {
progress = [];
io.emit('update', getCurrentServerState());

const filePath = path.join(__dirname, 'bootserver.json');
const file = fs.readFileSync(filePath, { encoding: 'utf-8' });

progress = Object.values(JSON.parse(file));
progress.forEach(line => {
line[0] = 1;
io.emit('update', getCurrentServerState());
execSync(line[2]);
line[0] = 2;
});
io.emit('update', getCurrentServerState());

res.sendStatus(200);
});

[...]

要理解 forEach,这里是我的虚拟 bootserver.json。一个数组包含三个值: state (0=wait, 1=wip, 2=done) 、 name 和 command 。

{
"0": [2, "0", "sleep 2"],
"1": [2, "A", "sleep 1"],
"2": [1, "b", "sleep 0.2"],
"3": [0, "C", "sleep 1"],
"4": [0, "d", "sleep 0.2"],
"5": [0, "E", "sleep 1"],
"6": [0, "f", "sleep 5"],
"7": [0, "G", "sleep 2"],
}

这是我用于监听消息的 Angular 代码:

const observable = new Observable<string>((observer: any) => {
io(url, { secure: true }).on('update', (msg: string) => {
observer.next(msg);
});
});

我希望有一种机制可以刷新/强制发出直接更新我的前端。有这样的吗?

最佳答案

您正在使用同步操作,它们会阻止事件循环,因此异步操作(例如网络)在事件循环可用之前可能无法继续。

您可以通过删除同步操作(使用异步操作重写)来修复此问题,以便允许事件循环在循环期间运行。

这是一种使用异步 I/O 进行编码的方法,并使用 async/await 更轻松地使循环工作:

const express = require('express');
const app = express();
const socketIO = require('socket.io');
const exec = require('child_process').exec;
const promisify = require('util').promisify;
const fsp = require('fs').promises;

const execP = promisify(exec);

app.post('/bootupserver', async function(req, res) {
progress = [];
io.emit('update', getCurrentServerState());

try {

const filePath = path.join(__dirname, 'bootserver.json');
const file = await fsp.readFile(filePath, { encoding: 'utf-8' });

progress = Object.values(JSON.parse(file));
for (let line of progress) {
line[0] = 1;
io.emit('update', getCurrentServerState());
await execP(line[2]);
line[0] = 2;
}
io.emit('update', getCurrentServerState());

res.sendStatus(200);
} catch(e) {
res.sendStatus(500);
}
});

I would expect, that there is a mechanism to flush/force the emit to straight update my frontend. Is there some kind of that?

不直接。您必须将循环的每次迭代放入 setTimeout() 中(因此无法使用常规的 for.forEach() 循环),以便在运行循环的下一次迭代之前给其他事物一个运行的机会。更好的选择是切换到异步设计,这样所有东西都可以协同运行。这就是 Node.js 的设计原理。

<小时/>

如果您好奇,util.promisify() 会特别对待 exec(),以便其回调看起来像 (err, stdio, stderr ) 而不是 (err, value) 的标准异步回调仍然可以正常工作(它在内部将两个结果更改为 {stdio, stderr} 所以它是可以从 promise 中得出的一个值)。您没有使用这些返回值,因此这里并不重要,但如果您使用它们,它们仍然可以正常工作。

关于javascript - 在 shell 执行期间无法使用 socket.io 发出当前服务器状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57600348/

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