-1

I think that some asynchronous stuff is happening that I cannot figure out Please tell how can I solve this with async-await if possible.

my code:

const {spawn} = require('child_process')


const getWeatherReport = (location) => {
    let dataToSend, result
    const python = spawn('python', [__dirname+'\\weathergetter.py', location.toString()])

    python.stdout.on('data', (data) => {
        console.log('Pipe data from python script ...');
        dataToSend = JSON.parse(data.toString().replace(/\'/g, '\"'));
        // console.log(dataToSend)
    })
    
    python.stderr.on('data', data => {
        console.error(`stderr: ${data}`)
    })
  
    python.on('close', (code) => {
        console.log(`child process close all stdio with code ${code}`);
        // console.log(dataToSend)
    })
    return dataToSend
    
}

var wea = getWeatherReport("kolkata")
console.log(wea)

Output:
undefined
Pipe data from python script ...
child process close all stdio with code 0

I want the function to return a json object which is assigned to dataToSend. Here I am actually working with a python script.

the python script has no problem. When I console.log(dataToSend) inside python.stdout.on() and python.on() as commented out in the code, the json objects gets printed to the console. But I cannot make the function return the json object.

Please refer to these for what I was following:

NOTE: Please don't mark this question as duplicate as it was done to my last question. I can understand that there are many posts on this topic in stack overflow already. But it is not helping in my case.

What I tried after my previous post was closed:

const {spawn} = require('child_process')


const getWeatherReport = async (location) => {
    let dataToSend
    const python = spawn('python', [__dirname+'\\weathergetter.py', location.toString()])

    python.stdout.on('data', async (data) => {
        console.log('Pipe data from python script ...');
        dataToSend = JSON.parse(data.toString().replace(/\'/g, '\"'));
        // console.log(dataToSend)
    })
    
    python.stderr.on('data', data => {
        console.error(`stderr: ${data}`)
    })
  
    python.on('close', (code) => {
        console.log(`child process close all stdio with code ${code}`);
        // console.log(dataToSend)
    })
    return  await dataToSend
    
}

var wea = await getWeatherReport("kolkata")
console.log(`data: ${ await wea}`)
Curious Learner
  • 1,182
  • 1
  • 4
  • 17
  • I posted this question because --- Your post has been associated with similar questions. If these questions don’t resolve your question, **ask a new one**. – Curious Learner Oct 25 '21 at 05:13
  • If you disagree with closure as duplicate, the proper response is to [edit] your post and explain exactly what is different and why. Asserting that it just _is_ different is not enough. See ["This question already has answers here" - but it does not. What can I do when I think my question's not a duplicate?](//meta.stackoverflow.com/q/252252/4642212) and [Should I really ask the same question again if the old one was closed as a duplicate?](//meta.stackoverflow.com/q/401721/4642212). – Sebastian Simon Oct 25 '21 at 11:40
  • Voting to close again because exactly the same `Promise`–`resolve` approach was suggested in the linked posts. – Sebastian Simon Oct 25 '21 at 11:42

1 Answers1

2

Since you're not using async/await or a callback, you're returning dataToSend before it has had the time to be populated by the data callback.

If you want to use async/await, you'll need to wrap things in a new Promise here. It's also a good idea to gather all the output from the subprocess before decoding only at the end, since there's no guarantee all of the JSON will be delivered in a single event.

const { spawn } = require("child_process");

const getWeatherReport = (location) => {
  return new Promise((resolve, reject) => {
    let buf = "";
    const python = spawn("python", [
      __dirname + "\\weathergetter.py",
      location.toString(),
    ]);

    python.stdout.on("data", (data) => {
      buf += data;
    });

    python.stderr.on("data", (data) => {
      console.error(`stderr: ${data}`);
    });

    python.on("close", (code) => {
      if (code !== 0) {
        return reject(`child process died with ${code}`);
      }
      const dataToSend = JSON.parse(buf.toString().replace(/\'/g, '"'));
      return resolve(dataToSend);
    });
  });
};

async function main() {
  var wea = await getWeatherReport("kolkata");
  console.log(wea);
}
main();
AKX
  • 152,115
  • 15
  • 115
  • 172