1

No matter what I try, I cannot get my data to print as it comes in. I tried this tutorial:

https://jakearchibald.com/2016/streams-ftw/

This SO post: How to handle streaming data using fetch? (and a several other SO posts I can't recall) And, tried reading the docs: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams

test.py

import time
import sys
for i in range(1,10):
  print('test', i)
  time.sleep(.5)
  sys.stdout.flush()

server.js

firmwareRouter.get('/run_test', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-control': 'no-cache' });
  const pathToExample = '/server/path/to/test.py';
  const { spawn } = require('child_process');
  const pythonProcess = spawn('python', [pathToExample]);
  pythonProcess.stdout.on('data', (data) => {
    // console.log(data.toString());
    res.write(data);
  });
  pythonProcess.on('close', (code) => {
    res.end('Process has ended');
  });
});

Firmware.js (Version 1)

export default function Firmware(props) {
  const [data, setData] = useState('');
  async function runTest() {
    try {
      const url = 'api/firmware/run_test'
      const request = {
        method: 'GET',
        headers: {
          'Content-Type': 'text/event-stream'
        },
      }
      const res = await fetch(url, request);
      const reader = res.body.getReader();
      const chunks = [];
      const decoder = new TextDecoder('utf-8');
      let done, value;
      while (!done) {
        ({ value, done } = await reader.read());
        value = decoder.decode(value);
        if (done) {
          return chunks;
        }
        console.log(value);
        chunks.push(value);
        setData(value);
      }
    } catch (err) {
      console.log('frontend:Firmware', err);
    }
  }

  return (
    <Fragment>
      {data}
      <button onClick={() => runTest()}>Run Test </button>
    </Fragment >
  )
}

Firmware.js (Version 2)

export default function Firmware(props) {
  const [data, setData] = useState('');
  async function runTest() {
    const url = 'api/firmware/run_test'
    const request = {
      method: 'GET',
      headers: {
        'Content-Type': 'text/event-stream'
      },
    }
    fetch(url, request).then((res) => {
      let reader = res.body.getReader();
      let decoder = new TextDecoder();

      reader.read().then(function processResult(result) {
        if (result.done) return;
        console.log(decoder.decode(result.value, { stream: true }))
        return reader.read().then(processResult);
      })
    })
  }
// return ()

No matter what, it only prints to the browser once the process has finished. I need it to print as the python script prints. What am I missing here?

1 Answers1

0

Okay... So, one "solution" is to build it. After I built the app (npm run build), it worked.

Note: I am serving my app from express/node.

It seems to be a webpack or middleware issue between the backend and frontend and using a Proxy. I am going to try to use CORS, turn off React's proxy and go from there.