nodejs поток socketio, используя тот же поток от клиента - PullRequest
0 голосов
/ 14 марта 2020

Я пытаюсь отправить файл, используя stream от client до server, когда сервер запрашивает его. Затем сервер отправляет поток во внешний интерфейс для установки его в качестве src тега html5 audio. Первый раз, когда я делаю запрос, я получаю ответ без проблем. Но при следующей попытке клиент все еще отправляет старый поток (поток первого запроса), и это приводит к ошибке TypeError: Cannot read property '_read' of null.

Пожалуйста, найдите код ниже

Внешний интерфейс:

getSong = (songPath) => {
    fetch('/song', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ path: songPath, userId: this.state.userId })
    }).then(res => {
      const reader = res.body.getReader();
      return new ReadableStream({
        start(controller) {
          return pump();
          function pump() {
            return reader.read().then(({ done, value }) => {
              if (done) {
                controller.close();
                return;
              }
              controller.enqueue(value);
              return pump();
            });
          }
        }
      })
    })
      .then(stream => new Response(stream))
      .then(response => response.blob())
      .then(blob => URL.createObjectURL(blob))
      .then(url =>
        this.setState({ songData: url });
      })
  }

Nodejs бэкэнд:

app.post('/song', async (req, res) => {
    const songPath = req.body.path;
    const userId = req.body.userId;
    console.log(songPath);
    if (!fsHandler.indexMap[userId]) {
        res.status(404).send('User not found - ' + userId);
    } else if (!fsHandler.indexMap[userId].socketId) {
        res.status(404).send('User socket not connected - ' + userId);
    } else {
        fsHandler.fetchSong(req.body, res, (stream,res) => {
            console.log("Stream readable ? - " + stream.readable);
            stream.pipe(res, { end: false });
            stream.on('end', () => {
                res.end();
                console.log("Song sent successfully!")
            });
        });
    }
});
....
....
fsHandler.fetchSong = (songReq, res, cb) => {
        const io = app.get('socketio');
        let socketId = fsHandler.indexMap[songReq.userId].socketId; // the client is connected using socket which I store in a map. I use that to get back the socket connection to emit.
        let socket = io.sockets.connected[socketId];
        console.log("Socket id - " + JSON.stringify(io.sockets.connected[socketId].id));
        socket.emit('get-song', { path: songReq.path });
        ss(socket).on('song', (stream,data) => {
            console.log('Sending song stream...')
            console.log(JSON.stringify(data));
            cb(stream, res);
        });
    }

Nodejs клиент (подключен с помощью socketio):

socket.on('get-song', (data) => {
    console.log('Requested song - ' + data.path);
    let stream = ss.createStream();
    let fileStream = fs.createReadStream(data.path);
    console.log("Sending song with length-" + fileStream.length);
    fileStream.pipe(stream);
    ss(socket).emit('song', stream, { name: data.path});
});

Ошибка:

Stream readable ? - true // my console log , added here for understanding where the error happens.
I:\project\node_modules\socket.io-stream\lib\iostream.js:97
  this.socket._read(this.id, size);
              ^

TypeError: Cannot read property '_read' of null

Я симпатичная убедитесь, что это связано с повторным использованием того же потока. Кроме того, я обнаружил, что событие on ('song') сервера происходит дважды, что связано с тем, что обработчик on дважды регистрируется в сокете. Я даже пытался исправить это так:

 if(!fsHandler.init){
      ss(socket).on('song', (stream,data) => {
      console.log('Sending song stream...')
      console.log(JSON.stringify(data));
      cb(stream, res);
      });
      fsHandler.init = true;
 }

Но это приводит к ошибке Error [ERR_STREAM_WRITE_AFTER_END]: write after end.

Пожалуйста, помогите мне.

...