javascript中的异步递归函数

时间:2017-02-17 14:02:35

标签: javascript asynchronous recursion web-audio web-audio-api

我正在尝试将mp3数据从我的服务器传输到客户端。我正在使用Ajax这样做。服务器每个请求发送50千字节。我写了两个函数:一个获取mp3数据,另一个播放它们。第一个函数占用50千字节,对它们进行解码并将解码后的数据存储在一个数组中,然后递归调用。只要数组中的第一个元素填充了数据,第二个函数就会开始播放。问题是,这适用于前50千字节,然后失败。我想要做的是保持我的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();
    }

}

1 个答案:

答案 0 :(得分:0)

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

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

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