【问题标题】:Passing an Array as an Argument Into SetTimeout Callback将数组作为参数传递给 SetTimeout 回调
【发布时间】:2012-01-15 08:12:09
【问题描述】:

我这两天一直在尝试将数组传递给 setTimeout 回调。

我一直在寻找整个互联网,并且我已经阅读了大约 10 个不同的 StackOverflow 问题及其所有答案。我一定错过了一些东西,因为在尝试了所有这些不同的东西之后它仍然不起作用。这是我现在的立场:

function testing(pixels){    

        return function(){
          for(i=0; i<pixels.length;i++){
                a = pixels[i][0];
                b = pixels[i][1];
                c = pixels[i][2];
                d = pixels[i][3];
                box = pixels[i][5];
                done = pixels[i][6];


                color_to_draw = done ? box.color:active_color;
                ctx.fillRect(a,b,c,d);        
                ctx2.clearRect(box.x-1,box.y-1,box.w,box.h);
                draw_colored_box(box.x, box.y, box.w, box.h, color_to_draw, box.alpha, true, ctx2);
            }
        };

}

function ias(pixel_batch){
  var color_to_draw; 
    ctx.fillStyle = "#000000";
    var a, b, c, d, e, box, done, i;


        setTimeout(testing(pixel_batch),pixel_batch[0][4]);
}

我已经摆脱了所有不同的解决方案,我发现我在这里的方法应该有效。我显然做错了什么,因为它不起作用。

问题在于,在函数 ias()pixel_batch.length 中等于 3,或者无论在该数组中放入多少项,即使在函数 testing()pixels.length 中也是正确的值,但是通过测试返回的函数内部,pixels.length` 等于 0...

最初,这是我尝试过的:

function ias(pixel_batch){
  var color_to_draw; 
    ctx.fillStyle = "#000000";
    var a, b, c, d, e, box, done, i;


        setTimeout((function(pixels){
            console.log(pixels.length);

            return function(){

              for(i=0; i<pixels.length;i++){
                    a = pixels[i][0];
                    b = pixels[i][1];
                    c = pixels[i][2];
                    d = pixels[i][3];
                    box = pixels[i][5];
                    done = pixels[i][6];


                    color_to_draw = done ? box.color:active_color;
                    ctx.fillRect(a,b,c,d);        
                    ctx2.clearRect(box.x-1,box.y-1,box.w,box.h);
                    draw_colored_box(box.x, box.y, box.w, box.h, color_to_draw, box.alpha, true, ctx2);
                }
            };
        })(pixel_batch),pixel_batch[0][4]);
}

相信它不需要通过外部定义的函数来完成,但此时我已经开始尝试任何/一切。

如何将pixel_batch(传递给ias()的参数)放入setTimeout的回调中?

[编辑/更新] 这是实际调用ias()的代码:

function redraw_boxes(){

    //This loop simply draws the active boxes again, on top of the previous set.
    //At this point in time there is no need to clear the canvas at all.
    var i; var i2; var box;
    var temp_pixelation_array = pixelation_array.slice(0);
    var x_mod; var y_mod; 
    var random_array_key;
    var max_runs;
    var the_pixel_batch = [];
    var num_pixels_per_batch = 3;
    var speed_to_pixelate = 3;
    var done;
    var temptimer=0;
    var timers = [];
    for(i=0;i<newly_acquired_boxes.length;i++){    
    temptimer=0;

    temp_pixelation_array = pixelation_array.slice(0);
        max_runs = temp_pixelation_array.length;
            box = boxes[newly_acquired_boxes[i].column][newly_acquired_boxes[i].row];

        for(i2 = 0; i2<max_runs;i2++){

           random_array_key = ~~((Math.random()*temp_pixelation_array.length));

            x_mod = temp_pixelation_array[random_array_key][0];
            y_mod = temp_pixelation_array[random_array_key][1];
            temp_pixelation_array.splice(random_array_key,1);

            done = i2<max_runs-1 ? true:true ; 
            the_pixel_batch.push([box.x+x_mod, box.y+y_mod, particle_size, particle_size,temptimer,box,done]);
            if(the_pixel_batch.length>= num_pixels_per_batch){                
                ias(the_pixel_batch);
                the_pixel_batch.length = 0;
                temptimer += num_pixels_per_batch*speed_to_pixelate;
            }




        }






    }
    newly_acquired_boxes.length=0;


}

[2 编辑/更新 2]

我希望我能接受你所有的答案,因为你在技术上都是正确的。一开始没有给你正确的信息是我的错。我投了所有人的票,因为你们都应该得到答案,只是你不能用提供的信息给我。

【问题讨论】:

  • 乍一看,您的方法至少看起来不错
  • 我认为我们需要查看一些数据以便进行测试。我真的不明白你为什么要调用一个首先返回一个函数的函数。在ias 中只调用了一个setTimeout,因此回调具有对该函数调用的变量值的独占访问权。
  • 将你的功能分解成它的基本部分,它似乎工作:jsfiddle.net/pxaXq
  • 我只使用返回函数的函数,因为我被驱使尝试一切。最初我只是在 setTimeout 中定义了函数
  • @JonathonG:这个函数有没有任何东西?或者是否有任何其他代码可以访问pixels 数组,可以在setTimeout 发生之前清除它。我们在这里缺少一些东西。

标签: javascript arrays scope settimeout


【解决方案1】:

这里有一篇很好的文章解释了如何做到这一点:https://gullan.org.uk/passing-parameters-function-settimeout

这是结论:setTimeout(function(){myFunction(parameter)}, myTimeout);

【讨论】:

  • 我试过这个,但无济于事。由于某种原因,当我尝试在回调函数中访问它时,传入的数组长度仍然为 0
  • 我认为代码调用的是testing()返回的函数,所以直接在setTimeout中(而不是在闭包中)调用testing(...)是正确的。
  • 您的匿名函数无法关闭参数 - 当 setTimeout 实际应用您的函数时,它的范围内没有定义的变量像素。 David 的回答总结了我的回答,没有详细说明其他修复方法。
  • @TetsujinnoOni:它有形参pixels,不是吗? setTimeout((function(pixels){
  • @TetsujinnoOni:没有理由相信它不会关闭它,除了问题。也就是说,它应该起作用。在闭包/作用域方面,变量和形式参数之间几乎没有区别。
【解决方案2】:

扩展大卫的回答:我认为您可能想要的是这样的:

function draw () {
      for(i=0; i<pixels.length;i++){
            a = pixels[i][0];
            b = pixels[i][1];
            c = pixels[i][2];
            d = pixels[i][3];
            box = pixels[i][5];
            done = pixels[i][6];


            color_to_draw = done ? box.color:active_color;
            ctx.fillRect(a,b,c,d);        
            ctx2.clearRect(box.x-1,box.y-1,box.w,box.h);
            draw_colored_box(box.x, box.y, box.w, box.h, color_to_draw, box.alpha, true, ctx2);
        }
    }

function ias(pixel_batch){
  var color_to_draw; 
    ctx.fillStyle = "#000000";
    var a, b, c, d, e, box, done, i;
    setTimeout(function () {draw(pixel_batch)},pixel_batch[0][4]);
}

函数不需要返回函数,直接用闭包调用即可。

【讨论】:

  • 无论是这个,还是通过在我的回答中创建一个范围内的副本来关闭函数的参数,都应该有效。
  • 那么看来问题一定出在其他地方了。调用 ias(the_pixel_batch) 的函数在调用后将 the_pixel_batch[] 重置为 0 长度是否重要?
  • 是的,因为即使是我的复制策略也只是复制引用而不是复制数组。
【解决方案3】:

你的问题就在这里:

ias(the_pixel_batch);
the_pixel_batch.length = 0;

您在 setTimeout 运行之前清除阵列。


你应该这样做:

pixel_batch.length = 0;

...在setTimeout 回调中。

function ias(pixel_batch) {
    ctx.fillStyle = "#000000";

    setTimeout(function () {
        var color_to_draw, a, b, c, d, e, box, done, i;

        for (i = 0; i < pixels.length; i++) {
            a = pixels[i][0];
            b = pixels[i][1];
            c = pixels[i][2];
            d = pixels[i][3];
            box = pixels[i][5];
            done = pixels[i][6];

            color_to_draw = done ? box.color : active_color;
            ctx.fillRect(a, b, c, d);
            ctx2.clearRect(box.x - 1, box.y - 1, box.w, box.h);
            draw_colored_box(box.x, box.y, box.w, box.h, color_to_draw, box.alpha, true, ctx2);
        }
        pixel_batch.length = 0; // <<--- RIGHT HERE
    }, pixel_batch[0][4]);
}

【讨论】:

  • 我认为它被复制到 ias() 函数内的变量 pixel_batch,这就是为什么我认为这不是问题。
  • 不敢相信我曾经遇到过这个问题,现在又遇到了。解决方法是在ias()开头做pixel_batch = pixel_batch.slice(0);......
  • @JonathonG:是的,要进行浅拷贝,您需要.slice(),或者只是跳过切片,并在回调中清除数组。但是,是的,它是指向传递给函数的同一个数组的指针。
  • 我无法清除回调中的数组,因为在第一个 setTimeout 执行之前,ias 函数会运行 30 到 300 次。
  • 并且每次 setTimeout 回调运行时,它需要在数组中有 3 个不同的像素。我想我可以使用某种传入的偏移量来修改i,但是使用slice(0) 方法有什么缺点吗?
【解决方案4】:

您是否正在修改pixel_batch 数组之后 调用ias()之前 超时已执行?如果是这样,您可以传递数组的副本:

setTimeout(testing(pixel_batch.slice(0)),pixel_batch[0][4]);

(注意.slice() 只对数组进行一级深拷贝...)

【讨论】:

    猜你喜欢
    • 2010-11-14
    • 2020-05-15
    • 2020-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多