最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to return value from a child process in a function? - Stack Overflow

programmeradmin6浏览0评论

I spawn a python child process in javascript (for coding a Bot with Microsoft Botframework) like this:

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;
        }
    });
}

I want output to be returned as the value of the function searchForRelevanceDoc(). How can this be done? I am not able to use await context.sendActivity(output) instead of the return statement. Error message:

TypeError: Cannot perform 'get' on a proxy that has been revoked

Function searchForRelevanceDoc is called like so:

//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)
        // ...
    }
}

I spawn a python child process in javascript (for coding a Bot with Microsoft Botframework) like this:

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;
        }
    });
}

I want output to be returned as the value of the function searchForRelevanceDoc(). How can this be done? I am not able to use await context.sendActivity(output) instead of the return statement. Error message:

TypeError: Cannot perform 'get' on a proxy that has been revoked

Function searchForRelevanceDoc is called like so:

//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)
        // ...
    }
}

Share Improve this question edited Nov 30, 2019 at 13:26 Lady_Hangaku asked Nov 29, 2019 at 14:59 Lady_HangakuLady_Hangaku 1191 silver badge11 bronze badges 1
  • show stacktrace. – Marios Nikolaou Commented Nov 29, 2019 at 15:24
Add a ment  | 

3 Answers 3

Reset to default 7

The easiest way to return/resolve output from searchForRelevantDoc, using async/await is to use events.once which was added in Node 11.13.0, and wait for close event of py

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;
}

If you're using an older version of Node, you can wrap it in a 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;
}

Then when calling searchForRelevantDoc you need to use await or .then

class MyBot {

    // constructor...

    async onTurn(context) {
        // ...
        var search_engine_answer = await pysearch.searchForRelevantDoc(context);
        context.sendActivity(search_engine_answer)
        // ...
    }
}

@Marcos Casagrande's answer is more beautiful, I just wanted to add the promise solution as well.

You can just return a new Promise and wrap the stdout.on inside the 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 so whenever you declare a promise the function will start to run. So basically the event will be attached.

Make your function return new Promise((resovle, reject) => ...) and resolve needed value

发布评论

评论列表(0)

  1. 暂无评论