reactjs “multipart/x-mixed-replace”http响应在不再需要时未关闭

a14dhokn  于 2023-03-08  发布在  React
关注(0)|答案(2)|浏览(261)

我们展示的是一个使用html img标签的mjpeg视频流。为此,我们有多种实现,具体取决于视频流的提供商。
流媒体视频运行良好。切换流媒体也可以。但切换到不同类型的流媒体就不行了。此时,当前流媒体不会关闭,第二个流媒体会打开。经过几次这样的切换后,无法再发出http请求,浏览器选项卡会冻结。
我可以用下面的代码重现它:

interface StreamProps {
    mjpegUrl: string;
}

export const StreamType1: React.FC<StreamProps> = ({ mjpegUrl }) => {
    return <img src={mjpegUrl} />;
};

export const StreamType2: React.FC<StreamProps> = ({ mjpegUrl }) => {
    return <img src={mjpegUrl} />;
};

interface Props {
}

export const VideoStream: React.FC<Props> = () => {
  const [toggle, setToggle] = useState(true);
  
  return (
    <div>
      <button onClick={() => setToggle((current) => !current)}>
        Switch!
      </button>
      {toggle
        ? <StreamType1 mjpegUrl="http://localhost/stream1" /> 
        : <StreamType2 mjpegUrl="http://localhost/stream2" />}
    </div>
  );
};

需要注意的一点是,如果我对这两者使用相同的流类型,这个问题就不会发生。类似于更新mjpegUrl属性。

{toggle
        ? <StreamType1 mjpegUrl="http://localhost/stream1" /> 
        : <StreamType1 mjpegUrl="http://localhost/stream2" />}

为什么会发生这种情况?如何解决?

kqlmhetl

kqlmhetl1#

我想我知道了。
更新imgsrc属性将停止当前请求并发送一个新请求。这就是为什么更新同一个组件没有问题的原因。
当使用同一类型的不同组件时,React足够智能,可以重用现有组件,这意味着src属性会被更新,请求也会停止。
当使用不同类型的不同组件时,React无法重用该组件。因此,imgsrc属性不会更新,当前请求也不会停止。
要解决此问题,可以使用两步更新。首先更新现有组件并设置一个空字符串。然后更新为新组件和值。困难在于,当您有一个很深的组件树,其中一个组件被替换或删除时,您仍然有一个打开的连接。
最后,我的解决方案基于https://stackoverflow.com/a/52328525/9271844

const [frame, setFrame] = useState("");

useEffect(() => {
  const controller = new AbortController();
  fetch(url, { signal: controller.signal })
    .then(response => { 
      // Read stream and store images in 'setFrame' using URL.createObjectURL.
      // Don't forget to call URL.revokeObjectURL when image is no longer needed.
    });
  
  return () => controller.abort();
});

return <img src={frame} />
j8yoct9x

j8yoct9x2#

stop()将结束所有当前的流。将它放在useEffect钩子中,以便在离开页面时停止流。

useEffect(() => {
        return () => {
            // This stops the stream
            window.stop()
        }
    }, [])

相关问题