【问题标题】:pass loop parameters to closure inside closure将循环参数传递给闭包内的闭包
【发布时间】:2012-11-13 15:29:22
【问题描述】:

我正在尝试将 for 循环参数 i 提供给内部闭包,因为我想识别我的解码音频(放在缓冲区内)。

此代码给出错误:e 未定义。但是,它在删除 )(test) 时起作用,我的意思是对于所有结果, test 等于 list.length 但是我希望它们在调用时具有当前参数 i 的值。

for (var i = 0; i < list.length; i++) { //load in every url
    requestArray.push(new XMLHttpRequest());
    requestArray[i].open('GET', list[i].url, true);
    requestArray[i].responseType = 'arraybuffer';
    test = i;
    requestArray[i].onload = (function (e) {
        //Async method: ASK J
        context.decodeAudioData(e.target.response, (function (buffer) { //Async method
            console.log(test);
            if (!buffer) {
                alert('error decoding file data: ');
                return;
            }
        })(test),

        function (e) {
            console.log('Error decoding audio file', e)
        });
    })(test);

    requestArray[i].onerror = function () {
        alert('BufferLoader: XHR error');
    }

    requestArray[i].send();
}

【问题讨论】:

  • onload 中的“上下文”来自哪里。我很惊讶没有抛出错误
  • context 在脚本的开头定义:它是 webaudio 的东西,但它与这个问题无关:var context = new webkitAudioContext();

标签: javascript loops closures parameter-passing


【解决方案1】:
for (var i=0; i<list.length; i++){
    requestArray.push(new XMLHttpRequest());
    requestArray[i].open('GET', list[i].url, true);
    requestArray[i].responseType = 'arraybuffer';
    requestArray[i].onload = (function (i) {
        return function (resp) {
            // i: index in requestArray
            // resp: the response object passed when the onload event occurs

            context.decodeAudioData(
                resp.target.response,
                (function(test) {
                    return function (buffer) {
                        console.log(test);
                        if (!buffer) {
                            alert('error decoding file data: ');
                            return;
                        }
                    }
                }(i)),
                function(e) { console.log('Error decoding audio file', e)}
            );
        }
    }(i));
    requestArray[i].onerror = function() {
        alert('BufferLoader: XHR error');
    }
    requestArray[i].send();
}



请注意,要创建闭包,函数必须返回一个函数。

这是一个闭包:

(function(){
    var a = "b";
    return function(){ alert(b); }
}());


这是尽快评估:

(function(){
    var a = "b";
}());

【讨论】:

  • 但是 decodeAudioData 在哪里适合呢? decodeAudioData 也是一个回调函数;我的内心封闭在哪里?
【解决方案2】:

您的代码没有按照您的意愿行事。您无需将test 绑定为参数,而是立即使用参数test 调用匿名函数,并将它们的返回结果作为参数传递给decodeAudioData。我建议先解决这个问题。例如。通过使用Function.prototype.bind

【讨论】:

  • 您能详细说明一下吗?我对原型设计不是很熟悉
  • 这与原型设计无关。你只需要写myFunc.bind(window, test),这将把myFunc变成一个函数对象,当被调用时,将test作为第一个参数传递给myFuncwindow作为this(接收对象)。
  • .bind 对于某些应用程序来说是一个棘手的函数,因为它不仅将参数绑定到函数,还绑定了调用者实例。
  • 对。来自 Google Closure 库的goog.partial 解决了这个问题:)
【解决方案3】:

我想我会尝试这样的语法(我也会采用更模块化的方法,有几个声明的函数)

for (var i=0; i<list.length; i++){ //load in every url
        requestArray.push(new XMLHttpRequest());
        requestArray[i].open('GET', list[i].url, true);
        requestArray[i].responseType = 'arraybuffer';
        test = i;
        requestArray[i].onload = (function(outerIndex){
                        return function (e) { //Async method: ASK J
                context.decodeAudioData(e.target.response, 
                    (function(index){
                        return function(buffer) {  //Async method
                            console.log(index);
                            if (!buffer) {
                                alert('error decoding file data: ');
                                return;
                            }
                        };  
                    })(outerIndex),  function(e) { console.log('Error decoding audio file', e)});
        };})(test);


        requestArray[i].onerror = function() {
            alert('BufferLoader: XHR error');
        }

        requestArray[i].send();
    }

【讨论】:

    【解决方案4】:

    当你放

    })(test);
    

    您在当时(而不是在事件发生时)运行该函数,通过了类似 e 的测试。 我不明白“e 是未定义的”e 是 i。

    您可以尝试将“var”放在定义变量 test 的位置并删除“)(test)”吗?我认为问题在测试范围内。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 2012-12-26
      • 2011-06-12
      相关资源
      最近更新 更多