skip to Main Content

There is a problem with following code.

async function loadVideo (src, crossOrigin)
{
   let video  = makeVideo (src, crossOrigin);

   return new Promise((resolve, reject) =>
   {
       Promise.allSettled ([
            new Promise ( (resolve, reject) => {video.addEventListener('playing',     () => {resolve(1);}, true )}   ),
            new Promise ( (resolve, reject) => {video.addEventListener('timeupdate',  () => {resolve(1);}, true )}   )   ])
            .then((values) => 
       {
         resolve(video);
       });
   });
}

I use the code for creating webgl2 textures. The problem is that event callbacks for playing is called ever again when video begins, and timeupdate event is called permanently. It doesn’t cause big nor visible issues, but I need them to be called only once. Is there a way to remove listeners after first invocation?

See full code in following snippet:

function makeVideo (src, crossOrigin)
{
   let video  = document.createElement("video");
   if (crossOrigin) video.crossOrigin  =  crossOrigin;
   video.src         =  src;
   video.autoplay    = true;
   video.playsInline = true;
   video.muted       = true;
   video.loop        = true;
   video.play();
   return video;
}

async function loadVideo (src, crossOrigin)
{
   let video  = makeVideo (src, crossOrigin);
   video.width = 300;
   return new Promise((resolve, reject) =>
   {
       Promise.all ([
            new Promise ( (resolve, reject) => {video.addEventListener('playing',     () => {resolve(1);}, true )}   ),
            new Promise ( (resolve, reject) => {video.addEventListener('timeupdate',  () => {resolve(1);}, true )}   )   ])
            .then((values) => 
       {
         resolve(video);
       });
   });
}
document.addEventListener('DOMContentLoaded', async () => 
{
   loadVideo ("https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4")
      .then(vd => {document.body.appendChild(vd)});
});

2

Answers


  1. You can unsubscribe right before ending the promise:

    function makeVideo(src, crossOrigin) {
      let video = document.createElement('video');
      if (crossOrigin) video.crossOrigin = crossOrigin;
      video.src = src;
      video.autoplay = true;
      video.playsInline = true;
      video.muted = true;
      video.loop = true;
      video.play();
      return video;
    }
    
    async function loadVideo(src, crossOrigin) {
      console.log('loadVideo');
      let video = makeVideo(src, crossOrigin);
      video.width = 300;
      return new Promise((resolve, reject) => {
        Promise.all([
          new Promise((resolve, reject) => {
            const playingCallback = () => {
              console.log('playing');
              video.removeEventListener('playing', playingCallback, true);
              resolve(1);
            };
            video.addEventListener('playing', playingCallback, true);
          }),
          new Promise((resolve, reject) => {
            const timeupdateCallback = () => {
              console.log('timeupdate');
              video.removeEventListener('timeupdate', timeupdateCallback, true);
              resolve(1);
            };
            video.addEventListener('timeupdate', timeupdateCallback, true);
          }),
        ]).then((values) => {
          resolve(video);
        });
      });
    }
    
    document.addEventListener('DOMContentLoaded', async () => {
      loadVideo(
        'https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4'
      ).then((vd) => {
        document.body.appendChild(vd);
      });
    });
    Login or Signup to reply.
  2. You can use the once option.

    Here is how:

    async function loadVideo (src, crossOrigin)
    {
       let video  = makeVideo (src, crossOrigin);
    
       return new Promise((resolve, reject) =>
       {
           Promise.allSettled ([
                new Promise ( (resolve, reject) => {video.addEventListener('playing',     () => {resolve(1);}, { once: true } )}   ),
                new Promise ( (resolve, reject) => {video.addEventListener('timeupdate',  () => {resolve(1);}, { once: true } )}   )   ])
                .then((values) => 
           {
             resolve(video);
           });
       });
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search