Вызов python скрипта в node.js

Имеется два скрипта на Node.js и на python. Пытаюсь, чтобы python-скрипт вызывался у меня в js-скрипте и присылал мне json, но моя функция в js возвращает пустой массив. Что надо исправить?

И второе, как в js-скрипте мне сделать так, чтобы он засыпал допустим на 3 секунды (т.е. нужен аналог time.sleep(3) в python).

Скрипт на nodejs:

function draw() {
    const spawn = require("child_process").spawn;
    const pythonProcess = spawn('python', ["./generationData.py"]);
    let lst = [];
    pythonProcess.stdout.on('data', data => {
        var myStr = data.toString();
        var obj = JSON.parse(myStr);
        lst.push(obj); 
    });
    return lst;
};

console.log(draw());

Скрипт на python:

from datetime import datetime
import time
import math
import json

def get_data(step):
    id_val = 'prop.fuel'
    x = int(str(datetime.now().timestamp()).replace('.', ''))
    y = math.sin(step*math.pi/180)

    data =  {
        'timestamp': x, 
        'value': y, 
        'id': id_val
    }

    return json.dumps(data)

if __name__ == '__main__':
    print(get_data(5))

Ответы (1 шт):

Автор решения: nörbörnën

Причина такого поведения в том, что lst возвращается после объявления обработчиков событий, а не после того как эти обработчики были вызваны.

Есть 2 эффективных способа решить задачу: Promise и callback.

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

(async () => {
  try {
    const lst = await drawAsync();
    console.log('async:', lst);
  } catch (err) {
    console.error('async error:', err);
  }
})();

drawCallback(([err, lst]) => {
  if (err) {
    console.error('cb error:', err);
  }
  console.log('cb:', lst);
});

async function drawAsync() {
  return new Promise((resolve, reject) => {
    const pythonProcess = spawn('python3', ["./generationData.py"]);

    let lst = [];
    pythonProcess.stdout.on('data', data => {
      var myStr = data.toString();
      var obj = JSON.parse(myStr);
      lst.push(obj);
    });

    pythonProcess.on('close', (code) => resolve(lst));

    pythonProcess.on('error', (err) => reject(err));

  });
}

function drawCallback(cb) {
  const pythonProcess = spawn('python3', ["./generationData.py"]);

  let lst = [];
  pythonProcess.stdout.on('data', data => {
    var myStr = data.toString();
    var obj = JSON.parse(myStr);
    lst.push(obj);
  });

  pythonProcess.on('close', (code) => cb([null, lst]));

  pythonProcess.on('error', (err) => cb([err, lst]));
}

Почитать про Promise.

Почитать про callback.


UPD на запрос про цикл и sleep:

(async () => {
  let count = 100;
  while (count--) {
    console.log('async:', await drawAsync());
    await delay(500);
  }
})();

async function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

UPD2 на запрос про бесконечный вызов на callback-ах:

let f;
(f = () => {
  drawCallback(([err, lst]) => {
    if (err) {
      console.error('cb error:', err);
    }
    console.log('cb:', lst);
    setTimeout(f, 1000);
  });
})();
→ Ссылка