【问题标题】:Asynchronous recursive functions in javascriptjavascript中的异步递归函数
【发布时间】:2023-03-11 14:47:01
【问题描述】:

我正在尝试将 mp3 数据从我的服务器流式传输到客户端。我正在使用 Ajax 执行此操作。服务器每个请求发送 50 KB。我写了两个函数:一个获取 mp3 数据,一个播放它们。第一个函数获取 50 KB,对其进行解码并将解码后的数据存储在一个数组中,然后递归调用自身。一旦数组中的第一个元素被数据填充,第二个函数就开始播放。问题是这仅适用于前 50 KB,然后它就失败了。我想要做的是让我的 get_buffer 函数保持运行,直到服务器告诉它不再发送数据,并让我的 play() 函数继续播放数据,直到数组中没有更多元素。

这是我的两个函数:

function buffer_seg() {
    // starts a new request
    buff_req = new XMLHttpRequest();

    // Request attributes
    var method = 'GET';
    var url = '/buffer.php?request=buffer&offset=' + offset;
    var async = true;

    // set attributes
    buff_req.open(method, url, async);
    buff_req.responseType = 'arraybuffer';

    // keeps loading until something is recieved
    if (!loaded) {
        change_icon();
        buffering = true;

    }


    buff_req.onload = function() {
        segment = buff_req.response;

        // if the whole file was already buffered
        if (segment.byteLength == 4) {
            return true;
        } else if (segment.byteLength == 3) {
            return false;
        }
        // sets the new offset
        if (offset == -1) {
            offset = BUFFER_SIZE;
        } else {
            offset += BUFFER_SIZE;
        }
        //decodes mp3 data and adds it to the array
        audioContext.decodeAudioData(segment, function(decoded) {
            buffer.push(decoded);
            debugger;
            if (index == 0) {
                play();
            }

        });


    }
    buff_req.send();
    buff_seg();
}

第二个功能:

function play() {

    // checks if the end of buffer has been reached
    if (index == buffer.length) {
        loaded = false;
        change_icon();
        if (buffer_seg == false) {
            stop();
            change_icon();
            return false;
        }
    }
    loaded = true;
    change_icon();

    // new buffer source
    var src = audioContext.createBufferSource();

    src.buffer = buffer[index++];

    // connects 
    src.connect(audioContext.destination);

    src.start(time);
    time += src.buffer.duration;
    src.onended = function() {
        src.disconnect(audioContext.destination);
        play();
    }

}

【问题讨论】:

    标签: javascript asynchronous recursion web-audio-api


    【解决方案1】:

    buffer_seg 的递归调用是在buffer_seg 的主体中,而不是在回调中,所以它会立即发生 - 不像您似乎打算的那样,在收到响应后。其次,这也意味着递归调用是无条件的,因为它应该基于先前的响应是否指示更多数据可用。如果这不仅仅是让您的浏览器崩溃,我不确定为什么。这也意味着流式音频块可能会被乱序推入缓冲区。

    所以首先我会考虑在检查流结束之后将递归调用移动到 onload 处理程序的末尾。

    在第二个函数中,你打算if (buffer_seg == false) 做什么?这个条件永远不会满足。您是否认为这是一种查看buffer_seg 的最后一个返回值的方法?这不是它的工作原理。也许你应该有一个两个函数都可以看到的变量,buffer_seg 可以设置,play 可以测试,或者类似的东西。

    【讨论】:

    • "offset" 变量告诉服务器从哪个字节开始服务器应该发送 mp3 音频。因此,如果偏移量发送到文件末尾或文件末尾之后,服务器会回复“完成”。我检查数组缓冲区的大小是否等于 4,而不是必须“完成”。然后它返回false。抱歉,这是我的错,应该是(buffer_seg() == false)。它在到达数组末尾时调用 buffer_seg() 函数,以查看 buffer_seg 是否会缓冲新数据或返回 false 指示 EOF。感谢您的回复
    • 是的,我知道你打算 offset 做什么。我不确定您为什么要指出这一点;当您编写代码时,响应可能会乱序返回,这并没有改变。此外,(buffer_seg() == false) 不会更好地工作,因为对buffer_seg 的调用将永远不会返回。无论如何,既然你有 buffer_seg 调用它自己,那么让 play 也调用它是没有意义的。
    • 是的,我同意你的观点,我可以看到这会导致脚本无法正确运行,我什至已经纠正了其中的一些问题。但是您对我如何编写一个将流数据保持在后台并将它们存储在一个数组中的函数以及另一个读取数组并存储它的函数有什么建议吗?或者知道如何缓冲 mp3 二进制数据并在整个缓冲完成之前播放它?
    猜你喜欢
    • 2018-02-24
    • 1970-01-01
    • 2018-10-11
    • 2019-02-20
    • 2016-09-21
    • 1970-01-01
    • 2021-12-12
    • 2017-06-27
    • 2015-08-12
    相关资源
    最近更新 更多