如何 return 来自函数中子进程的值?
How to return value from a child process in a function?
我在 javascript 中生成了一个 python 子进程(用于使用 Microsoft Botframework 编写机器人代码),如下所示:
async function searchForRelevantDoc (context) {
var msg = context.activity.text;
var spawn = require('child_process').spawn,
py = spawn('python', ['../path/to/file.py', msg]),
output = '';
py.stdin.setEncoding = 'utf-8';
py.stdout.on('data',
(data) => {
output += data.toString();
console.log('output was generated: ' + output);
});
// Handle error output
py.stderr.on('data', (data) => {
// As said before, convert the Uint8Array to a readable string.
console.log('error:' + data);
});
py.stdout.on('end', async function(code){
console.log('output: ' + output);
console.log(`Exit code is: ${code}`);
// "return" is probably wrong, what should be done instead?
return output;
}
});
}
我希望 output
被 return 编辑为函数 searchForRelevanceDoc()
的值。如何才能做到这一点?我无法使用
await context.sendActivity(output)
而不是 return 语句。错误信息:
TypeError: Cannot perform 'get' on a proxy that has been revoked
函数 searchForRelevanceDoc
的调用方式如下:
//in bot.js
const pysearch = require('../bboti/python-search');
class MyBot {
// constructor...
async onTurn(context) {
// ...
var search_engine_answer = pysearch.searchForRelevantDoc(context);
context.sendActivity(search_engine_answer)
// ...
}
}
制作你的函数
return new Promise((resovle, reject) => ...)
并解决所需的价值
@Marcos Casagrande 的回答更漂亮,我只是想添加 promise 解决方案。
您可以 return 一个 new Promise
并将 stdout.on
包装在 promise 中。
async function searchForRelevantDoc (context) {
...
return new Promise((res, rej) => {
py.stdout.on('end', async function(code){
console.log('output: ' + output);
console.log(`Exit code is: ${code}`);
// "return" is probably wrong, what should be done instead?
res(output);
})
});
}
Promises hot-load
因此无论何时您声明一个 promise 函数都会开始 运行。所以基本上活动都会附上。
从 searchForRelevantDoc
到 return/resolve output
的最简单方法,使用 async/await
是使用在 Node 11.13.0 中添加的 events.once
,并且等待 py
的 close
事件
const { once } = require('events'); // Added in Node 11.13.0
async function searchForRelevantDoc (context) {
var msg = context.activity.text;
var spawn = require('child_process').spawn,
py = spawn('python', ['../path/to/file.py', msg]),
output = '';
py.stdin.setEncoding = 'utf-8';
py.stdout.on('data', (data) => {
output += data.toString();
console.log('output was generated: ' + output);
});
// Handle error output
py.stderr.on('data', (data) => {
// As said before, convert the Uint8Array to a readable string.
console.log('error:' + data);
});
py.stdout.on('end', async function(code){
console.log('output: ' + output);
console.log(`Exit code is: ${code}`);
});
await once(py, 'close')
return output;
}
如果您使用的是旧版本的 Node,您可以将其包装在 new Promise
async function searchForRelevantDoc (context) {
// ...
// You can also check for `code` and reject if a non zero code is returned
await new Promise(resolve => py.on('close', resolve));
return output;
}
然后在调用searchForRelevantDoc
时需要使用await
或.then
class MyBot {
// constructor...
async onTurn(context) {
// ...
var search_engine_answer = await pysearch.searchForRelevantDoc(context);
context.sendActivity(search_engine_answer)
// ...
}
}
我在 javascript 中生成了一个 python 子进程(用于使用 Microsoft Botframework 编写机器人代码),如下所示:
async function searchForRelevantDoc (context) {
var msg = context.activity.text;
var spawn = require('child_process').spawn,
py = spawn('python', ['../path/to/file.py', msg]),
output = '';
py.stdin.setEncoding = 'utf-8';
py.stdout.on('data',
(data) => {
output += data.toString();
console.log('output was generated: ' + output);
});
// Handle error output
py.stderr.on('data', (data) => {
// As said before, convert the Uint8Array to a readable string.
console.log('error:' + data);
});
py.stdout.on('end', async function(code){
console.log('output: ' + output);
console.log(`Exit code is: ${code}`);
// "return" is probably wrong, what should be done instead?
return output;
}
});
}
我希望 output
被 return 编辑为函数 searchForRelevanceDoc()
的值。如何才能做到这一点?我无法使用
await context.sendActivity(output)
而不是 return 语句。错误信息:
TypeError: Cannot perform 'get' on a proxy that has been revoked
函数 searchForRelevanceDoc
的调用方式如下:
//in bot.js
const pysearch = require('../bboti/python-search');
class MyBot {
// constructor...
async onTurn(context) {
// ...
var search_engine_answer = pysearch.searchForRelevantDoc(context);
context.sendActivity(search_engine_answer)
// ...
}
}
制作你的函数
return new Promise((resovle, reject) => ...)
并解决所需的价值
@Marcos Casagrande 的回答更漂亮,我只是想添加 promise 解决方案。
您可以 return 一个 new Promise
并将 stdout.on
包装在 promise 中。
async function searchForRelevantDoc (context) {
...
return new Promise((res, rej) => {
py.stdout.on('end', async function(code){
console.log('output: ' + output);
console.log(`Exit code is: ${code}`);
// "return" is probably wrong, what should be done instead?
res(output);
})
});
}
Promises hot-load
因此无论何时您声明一个 promise 函数都会开始 运行。所以基本上活动都会附上。
从 searchForRelevantDoc
到 return/resolve output
的最简单方法,使用 async/await
是使用在 Node 11.13.0 中添加的 events.once
,并且等待 py
close
事件
const { once } = require('events'); // Added in Node 11.13.0
async function searchForRelevantDoc (context) {
var msg = context.activity.text;
var spawn = require('child_process').spawn,
py = spawn('python', ['../path/to/file.py', msg]),
output = '';
py.stdin.setEncoding = 'utf-8';
py.stdout.on('data', (data) => {
output += data.toString();
console.log('output was generated: ' + output);
});
// Handle error output
py.stderr.on('data', (data) => {
// As said before, convert the Uint8Array to a readable string.
console.log('error:' + data);
});
py.stdout.on('end', async function(code){
console.log('output: ' + output);
console.log(`Exit code is: ${code}`);
});
await once(py, 'close')
return output;
}
如果您使用的是旧版本的 Node,您可以将其包装在 new Promise
async function searchForRelevantDoc (context) {
// ...
// You can also check for `code` and reject if a non zero code is returned
await new Promise(resolve => py.on('close', resolve));
return output;
}
然后在调用searchForRelevantDoc
时需要使用await
或.then
class MyBot {
// constructor...
async onTurn(context) {
// ...
var search_engine_answer = await pysearch.searchForRelevantDoc(context);
context.sendActivity(search_engine_answer)
// ...
}
}