I want to display a stream of images in a browser component.
So far I’ve tried something like
function fetchData() {
fetch("data.png?")
.then((response) => response.blob())
.then((blob) => {
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height
myimage = new Image();
myimage.onload = function() {
ctx.drawImage(myimage, 0, 0,width,height);
}
const imageObjectURL = URL.createObjectURL(blob);
myimage.src = imageObjectURL;
}
...
setInterval(fetchData, 50);
This sort of works. But if I make the setInterval
period too short I start to get ERR_INSUFFICIENT_ RESOURCES error. I guess this is because fetch requests or responses pile up somewhere.
Ideally the drawing of a fetched image would trigger the next fetch. However I’m worried that sometimes no drawing will take place or a fetch might not complete in which case the process would stop.
Further I would like to have a few fetches in-flight to maximize performance and they should be completed in order, but without excessive buffering as the fetched data is interactive controlled from the browser so it is not like I would want to buffer a ten seconds worth of data.
So I’m looking for a general strategy implement above, I’m sure many people have worked on things like this before but I’ve not found examples.
2
Answers
You have load event to use
You can even add to error, but I would give up after x amount of retries
setInterval
isn’t appropriate because it doesn’t count the fetch and image load time.To get max FPS you should call
fetchData
immediately after the drawing.I suggest to draw with
requestAnimationFrame
to avoid possible image render tearing.You should have some
stopped
flag to be able to stop the infinite cycle.Also you should avoid requesting the context for each renders, it’s expensive.
Also you could use more ES6+ features and avoid creating intermediate 1 line variables: