代码之家  ›  专栏  ›  技术社区  ›  aman

为什么要在脚本末尾执行Sourceopen事件侦听器?

  •  3
  • aman  · 技术社区  · 7 年前

    我正在尝试使用媒体源扩展API创建媒体播放器。媒体播放器工作得很好,但我无法理解特定事件。这个 sourceopen 的addEventListner MediaSource 在第20行声明。这个 源打开 将源缓冲区添加到MediaSource,然后附加到源缓冲区。在第21行和第13行,我包含了控制台日志。执行网站时,控制台首先输出第13行的控制台日志。在我看来,应该首先显示第21行的控制台日志。我相信我无法理解 源打开 事件侦听器工作。有人能解释一下原因吗 源打开 事件侦听器在第13行之后被执行。谢谢

    如果有人不能理解我的问题,请在下面进行评论。

    01| <!DOCTYPE html>
    02| <html>
    03|   <head>
    04|     <meta charset="utf-8"/>
    05|   </head>
    06|   <body>
    07|     <video controls></video>
    08|     <script>
    09|       var video = document.querySelector('video');
    10|       var assetURL = 'frag_bunny.mp4';
    11|       var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
    12|       start();
    13|       console.log('2');
    14|
    15|       function start()
    16|       {
    17|         var mediaSource = new MediaSource;
    18|         video.src = URL.createObjectURL(mediaSource);
    19|       
    20|         mediaSource.addEventListener('sourceopen', function () {
    21|           console.log('1');
    22|           var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
    23|           fetchAB(assetURL, function (buf)
    24|           {
    25|             sourceBuffer.appendBuffer(buf);
    26|           });
    27|         });
    28|       } 
    29|
    30|       function fetchAB (url, cb)
    31|       {
    32|         var xhr = new XMLHttpRequest;
    33|         xhr.open('get', url);
    34|         xhr.responseType = 'arraybuffer';
    35|         xhr.onload = function ()
    36|         {
    37|           cb(xhr.response);
    38|         };
    39|         xhr.send();
    40|       };
    41|     </script>
    42|   </body>
    43| </html>
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   Alex Baban    7 年前

    A正确 start() 函数如下所示:

    function start() {
    
        // create an object, an instance of the MediaSource
        var mediaSource = new MediaSource;
    
        // to this `mediaSource` object add an event listener for the `sourceopen` event
        // and run the code inside the function when `sourceopen` happens
        mediaSource.addEventListener('sourceopen', function () {
            console.log('1');
            var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
            fetchAB(assetURL, function (buf) {
                sourceBuffer.appendBuffer(buf);
            });
        });
    
        // hey, `video` element, here is the source of the media I'd like you to play
        // it's not a simple url, is something more complex
        // , a `MediaSource` kind of thing
        // and it might take you some time to be ready        
        video.src = URL.createObjectURL(mediaSource);
    
    }
    

    现在,回到整个代码。。。,如果您告诉浏览器执行以下行:

    console.log('2');

    ,浏览器立即执行此操作没有问题,您将看到 2 立即在控制台中。

    但是,这件事:

    video.src = URL.createObjectURL(mediaSource);

    对于浏览器来说并不是那么简单。

    当您要求浏览器执行此操作时,浏览器是这样说的:“好吧,你让我执行,我现在就开始,你可以继续剩下的代码,但是,这一个对我来说并不那么容易……,我需要开始旋转一些轮子……,这将需要我一些时间……,而且,我不想在我准备好之前出去拿视频。我准备好后会告诉你。

    事实上,不是直接的我,浏览器,而是 mediaSource 对象,它是 MediaSource 这是我的( 浏览器的 )API,将通过提出 sourceopen 事件

    所以将此代码放在页面上时:

    mediaSource.addEventListener('sourceopen', function () {
      // do things
    });
    

    您正在告诉浏览器准备就绪时要做什么 源打开 已启动。

    让我们总结一下:

    12| start();

    // start() is called and starts to execute but it has something inside that 
    // will take some time before ready
    // as consequence `console.log('1')` does not happen yet
    

    13| console.log('2');

    // runs imediatelly  
    // you see "2" in the console
    

    。。。一些时间过去了,代码在里面 开始() 正在准备东西


    // the `sourceopen` event fires and a `function ()` 
    // the callback of `mediaSource.addEventListener('sourceopen'` 
    // starts to execute  
    

    21| console.log('1');

    // gets executed
    // you see "1" in the console