仅运行Javascript数组的函数,该函数在数组的一个元素上返回承诺

时间:2018-07-20 18:23:44

标签: javascript arrays animation promise

我还发布了其他问题,但我认为我应该简化事情

我有一个设置上下文的函数,然后调用第二个函数在上下文上画线。

我有这个:

var arr = [];

填充如下:

arr = [context,pre];

pre看起来像pre = [[{x:n,y:m}],[{x:j,y:k}]];

因此,基本上,我有一个数组pre,其中包含坐标数组。该数组与上下文一起推入arr

arr返回并推入最终数组,假设final_arr,现在看起来应该像这样:final_arr = [[context1,pre1],[context2,pre2],...]

我的目标是遍历final_arr并在由数组context确定的不同上下文上画线。例如,第一次迭代将访问final_arr[0]并包含context1,pre1。这两个值被发送到函数wrap(context, pre)中,该函数返回一个Promise。在此wrap函数内部,另一个函数称为animate(pre[i])。此函数采用pre中与坐标数组相对应的每个元素,并实际上使用动画帧绘制线。 animate()还会返回一个承诺。

当前,仅绘制了一条路径,这似乎是因为即使我正在遍历它,也仅使用了final_arr的一个值

我尝试进行迭代:

final_arr.reduce((a,c) => a.then(() => wrap(c[0],c[1])), Promise.resolve());

var temp = Promise.resolve();
var i = 0;
for (i = 0; i < arr.length; i++){
    //window.alert(arr[i].length)
    var ct = arr[i][0];
    var line = arr[i][1];
    temp.then(() => wrap(ct,line));
}

这是被调用的函数:

/*
*   Animation function draws a line between every point
*/              
var animate = function(p){
    return new Promise(function(resolve) {
        t = 1;
        var runAnimation = function(){
            if(t<p.length){
                context.beginPath();
                context.moveTo(p[t-1].x,p[t-1].y);
                context.lineTo(p[t].x,p[t].y);
                context.stroke();
                t++;
                requestAnimationFrame(function(){runAnimation()});
            } else {
                resolve()
            }
        };
        runAnimation();
    });
}
function wrap(ctx, lines){
    return new Promise(function(resolve) {
        var counter = 0;
        t = 1;
        var getAnimation = function(){
            if(counter < lines.length){
                context = ctx;
                lines.reduce((a, c) => a.then(() => animate(c)), Promise.resolve());
                counter++;
            } else {
                resolve()
            }
        };
        getAnimation();
    });
}

context中设置的wrap变量是js文件的全局变量

我希望以这种方式提出的问题能使我清楚我所遇到的问题

谢谢您的帮助

编辑:

尝试了fiddle

Edit2:

这很奇怪

if(final_arr.length == 1){
                    wrap(final_arr[0][0], final_arr[0][1]);
                } else if (final_arr.length == 2){
                    wrap(final_arr[0][0], final_arr[0][1]).then(wrap(final_arr[1][0], final_arr[1][1]));
                } else if (final_arr.length == 3){
                    wrap(final_arr[0][0], final_arr[0][1]).then(wrap(final_arr[1][0], final_arr[1][1])).then(wrap(final_arr[2][0], final_arr[2][1]));
                }

但是使用此功能时,线条是同时绘制的(可以,但不是首选)

1 个答案:

答案 0 :(得分:1)

编辑:只是在resolve的{​​{1}}语句中发现了丢失的if =>返回的Promise将永远无法解决...

在进行任何微优化之前,我建议先使用更简单的wrap版本:

wrap

在完成所有微任务(即在所有Promises之后)后,会调用

function wrap(ctx, lines){ return new Promise(function(resolve) { lines.forEach(p => animate(p, ctx)); resolve(); }); } 的回调-请参见When will requestAnimationFrame be executed?

因此,全局变量requestAnimationFrame的值对于所有回调均相同,即多次绘制同一行或出现竞争条件或取决于context内部的事物

我将只使用函数参数和局部变量来摆脱全局变量:

context