为什么在脚本末尾执行 Sourceopen 事件侦听器?
Why is the Sourceopen Event Listener being executed at the end of the script?
我正在尝试使用媒体源扩展 API 创建媒体播放器。媒体播放器运行良好,但我无法理解特定事件。 MediaSource
的 sourceopen
addEventListner 在第 20 行声明。 sourceopen
将 Source Buffer 添加到 MediaSource,然后附加到 Source Buffer。在第 21 行和第 13 行,我包含了控制台日志记录。 Website执行时,控制台首先输出第13行的控制台日志。从我的角度来看,第 21 行的控制台日志应该首先显示。我相信我无法理解 sourceopen
事件侦听器的工作原理。有人可以解释为什么 sourceopen
事件侦听器在第 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>
一个正确的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
});
您是在告诉浏览器在准备就绪且 sourceopen
已触发时要做什么。
让我们总结一下:
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
...一段时间过去了,start()
中的代码正在准备就绪
// 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
我正在尝试使用媒体源扩展 API 创建媒体播放器。媒体播放器运行良好,但我无法理解特定事件。 MediaSource
的 sourceopen
addEventListner 在第 20 行声明。 sourceopen
将 Source Buffer 添加到 MediaSource,然后附加到 Source Buffer。在第 21 行和第 13 行,我包含了控制台日志记录。 Website执行时,控制台首先输出第13行的控制台日志。从我的角度来看,第 21 行的控制台日志应该首先显示。我相信我无法理解 sourceopen
事件侦听器的工作原理。有人可以解释为什么 sourceopen
事件侦听器在第 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>
一个正确的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
});
您是在告诉浏览器在准备就绪且 sourceopen
已触发时要做什么。
让我们总结一下:
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
...一段时间过去了,start()
中的代码正在准备就绪
// 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