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.
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.
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}`)
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();