如何打开Child_process.spawn的"Promise"语法“异步/等待";句法 [英] how to turn Child_process.spawn's "Promise" syntax to "async/await" syntax
问题描述
所以我有这段代码,我试图全面了解async/await语法.以下是该代码的 Promise 版本:
So I have this code and I'm trying to understand the async/await syntax in full depth. The below is the Promise version of the code:
function callToolsPromise(req) {
return new Promise((resolve, reject) => {
let pipshell = 'pipenv';
let args = ['run', 'tools'];
req.forEach(arg => {
args.push(arg)
});
tool = spawn(pipshell, args);
tool.on('exit', (code) => {
if (code !== 0) {
tool.stderr.on('data', (data) => {
reject(data);
});
} else {
tool.stdout.on ('data', (data) => {
resolve(JSON.parse(data)):
});
}
});
})
}
我有一些要在tools/__ main__.py中执行的python代码,所以这就是为什么我称"pipenv".
I have some python code I want to execute in tools/__main__.py so that's why I'm calling "pipenv".
这是我尝试以 async/await 方式(实际上有效)编写它的方法:
Here's my attempt to do write it in async/await way (which actually works):
async function callToolsAsync(req) {
let pipshell = 'pipenv';
let args = ['run', 'tools'];
req.forEach(arg => {
args.push(arg)
});
let tool = spawn(pipshell, args);
for await (const data of tool.stdout) {
return data
}
}
但是我所做的只是从某人的示例中复制并粘贴,其中我有等待...
循环.
But all I did was copy and paste from someone's example where I have for await...
loop.
因此,我一直在尝试重写相同的代码,以便我可以真正理解它,但现在已经失败了好几天.
Therefore I've been trying to rewrite this same code so that I can actually understand it but I've been failing for days now.
还有其他方法可以使用 async/await 方式编写此代码,而无需使用 for await ...
循环吗?
Are there any other ways to write this code with async/await way without using the for await...
loop?
除了使用 .then
语法外,我不知道如何访问数据:
Also I have no idea how I can access data except for using the .then
syntax:
callToolsAsync(['GET','mailuser'])
.then(console.log)
我还如何从 resolve(data)
访问数据"?
How else would I access "data" from resolve(data)
?
非常感谢.
推荐答案
使用 async/await
编写代码的方法可能不是更好的>适用于Node中的异步(流块)语法.节点流专门实现了一个异步迭代器以允许这样做.
There are probably not better ways to write the code using async/await
than using the for async (chunk of stream)
syntax in Node. Node streams implement an asynchronous iterator specifically to allow doing so.
此关于2ality的文章具有更深入的解释和讨论.关于 Symbol.asyncIterator 的MDN文章 for-await ... of更广泛地介绍异步迭代.
This article on 2ality has more in-depth explanation and discussion. MDN articles on Symbol.asyncIterator and for-await...of cover asynchronous iteration more generally.
一旦决定使用异步迭代,就必须在 async
函数中使用它,该函数将返回一个Promise.
Once using asychronous iteration has been decided it must be used in an async
function, which will return a promise.
虽然在返回的promise上使用 then
子句是获取数据的完全正常的方式,但是您也可以 await
callToolsAsync(req)的结果
-当然,前提是该调用是在 async
函数内进行编码的,因此 await
在有效的上下文中.
While using a then
clause on the returned promise is a completely normal way of getting the data, you could also await
the result of callToolsAsync(req)
- provided of course that the call is coded inside an async
function so that await
is in a valid context.
以下代码 experiment 获得了
stdio
和 stderr
的输出,以及子进程的退出代码.它不使用Python或解析数据.
The following code experiment gets the
stdio
and stderr
output, and the exit code from a child process. It doesn't use Python or parse data.
main.js (键入要运行的 node main.js
)
// main.js
async function spawnChild() {
const { spawn } = require('child_process');
const child = spawn('node', ["child.js"]);
let data = "";
for await (const chunk of child.stdout) {
console.log('stdout chunk: '+chunk);
data += chunk;
}
let error = "";
for await (const chunk of child.stderr) {
console.error('stderr chunk: '+chunk);
error += chunk;
}
const exitCode = await new Promise( (resolve, reject) => {
child.on('close', resolve);
});
if( exitCode) {
throw new Error( `subprocess error exit ${exitCode}, ${error}`);
}
return data;
}
spawnChild().then(
data=> {console.log("async result:\n" + data);},
err=> {console.error("async error:\n" + err);}
);
child.js
// child.js
console.log( "child.js started"); // stdout
setTimeout( finish, 1000);
function finish() {
console.log( "child.js: finish() call"); // stdout
console.error("child exit using code 1"); // stderr
process.exit(1);
}
这表明
- 控制台警告节点中可读流的异步迭代仍处于试验阶段,
- 用于等待(流块)的
循环
循环似乎一直循环到关闭流为止-在这种情况下,这意味着await
将在不打开的流上等待"当时没有可用数据. - 从其管道中检索
stdout
和stderr
内容,并且由于检索是异步的,因此可以不按特定顺序获取退出代码. - 合并从另一个进程通过管道到达的大块数据不是可选的-子进程的控制台日志是单独传递的.
- A console warning that async iteration of a readable stream is still experimental in node,
- The
for await (chunk of stream)
loops seem to loop until the stream is closed - in this case meaning thatawait
will wait on an open stream that doesn't have data available at the time. - retrieving
stdout
andstderr
content from their pipes, and getting the exit code can be done in no particular order since retrieval is asynchronous. - Amalgamating chunks of data arriving through pipes from another process is not optional - console logs from the child process came through separately.
这篇关于如何打开Child_process.spawn的"Promise"语法“异步/等待";句法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!