返回promises的Javascript顺序函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了返回promises的Javascript顺序函数相关的知识,希望对你有一定的参考价值。

我需要按顺序运行函数才能以正确的顺序动画,但我遇到了一些问题。代码基本上检查一些条件并将值存储在数组中(未显示)。这些值作为参数传递给某些函数,这些函数需要按顺序运行。我正在使用承诺来实现这一目标

此代码将所需的函数(及其参数)存储在数组func_call

var func_call = [];
for (var i = 0; i < s_list.length; i++){
    //lower
    if (!isUpper) {
        canvas = document.getElementById("myCanvas");
        context = canvas.getContext("2d");
    //upper
    } else {
        canvas = document.getElementById("myCanvasUpr");
        context = canvas.getContext("2d");
    }
    func_call.push(function () {get_path(context, s_list[i], d_list[i], final_arr);});
    func_call.push(function () {draw_marker(context, s_list[i], d_list[i], isFirst[i], isLast[i]);});
}
func_call.push(function() {wrap(final_arr)});
func_call.reduce((cur, next) => cur.then(next()), Promise.resolve());

get_path就在这里

function get_path(context, source, desti, arr){
return new Promise(function(resolve) {
    var starting_points = string_to_point[source];
    var ending_points = string_to_point[desti];
    console.log("get path");
    console.log(starting_points);
    /*
    *   Define the variables
    *       i -> iterator count
    *       seg_1 -> points of starting exhibit and closest point on the path
    *       seg_2 -> points of ending exhibit and closest point on path
    *       main_path -> the points along the main path
    *       reverse_flag -> denotes whether the direction is forward or reverse 
    */
    var i;
    var seg_1 = [];
    var seg_2 = [];
    var main_path = [];
    var secondary_path = [];
    var reverse_flag = false;
    var secondary_flag = false;
    var primary_flag = false;
    var starting_point = starting_points[0];
    var ending_point = ending_points[0];
    var vertices = [];
    var pre = [];
    var secondary_vertices = [];
    var points = [];
    var secondary_points = [];

    /*
    *   Add the first two segments
    */
    if(starting_points.length == 3){
        for(var j = starting_points[0]; j <= starting_points[1]; j++){
            seg_1.push({x:point_coord[j][0] , y:point_coord[j][1]});
        }
        starting_point = starting_points[2];
    }
    if(ending_points.length == 3){
        for(var j = ending_points[0]; j <= ending_points[1]; j++){
            seg_2.push({x:point_coord[j][0] , y:point_coord[j][1]});
        }
        ending_point = ending_points[2];
    }
    if(starting_point == 260 && ending_point == 260){
        ending_point = -1;
    } else if (starting_point == 260){
        for(var j = 260; j <= 267; j++){
            seg_1.push({x:point_coord[j][0] , y:point_coord[j][1]});
        }
        starting_point = 72;
    } else if (ending_point == 260){
        for(var j = 260; j <= 267; j++){
            seg_2.push({x:point_coord[j][0] , y:point_coord[j][1]});
        }
        ending_point = 72;
    }


    /*
    *   Handles reverse direction. Switches starting and end points and sets the reverse_flag
    */
    if (ending_point != -1 && starting_point > ending_point){
        temp = starting_point;
        starting_point = ending_point;
        ending_point = temp;

        reverse_flag = true;
    }

    /*
    *   Add points to main_path
    */
    for (i = starting_point; i <= ending_point; i++){
        var b = point_coord[i];
        /*if(i >= 122){
            secondary_flag = true;
            secondary_path.push({x:b[0],y:b[1]});
        } else {
            primary_flag = true;
            main_path.push({x:b[0],y:b[1]});
        }*/
        primary_flag = true;
        main_path.push({x:b[0] , y:b[1]});
    }

    /*
    *   Creates the full path -> combination of seg_1, seg_2, and main_path
    */
    if(reverse_flag){
        if(primary_flag){
            if(secondary_flag){
                vertices = seg_1.concat(secondary_path.reverse());
                secondary_vertices = main_path.reverse().concat(seg_2);

                context.beginPath()
                context.arc(pathways[121][0], pathways[121][1], 8, 0, 2 * Math.PI);
                context.fillStyle = 'green';
                context.fill();

                context.beginPath();
                context.arc(pathways[122][0], pathways[122][1], 6, 0, 2 * Math.PI);
                context.fillStyle = 'red';
                context.fill();
            } else {
                vertices = seg_1.concat(main_path.reverse(),seg_2.reverse());
            }
        } else {
            if(secondary_flag){
                vertices = seg_1.concat(secondary_path.reverse(),seg_2);
            } else {

            }
        }
    } else {
        if(primary_flag){
            if(secondary_flag){
                vertices = seg_1.concat(main_path);
                secondary_vertices = secondary_path.concat(seg_2);

                context.beginPath();
                context.arc(pathways[122][0], pathways[122][1], 8, 0, 2 * Math.PI);
                context.fillStyle = 'green';
                context.fill();

                context.beginPath()
                context.arc(pathways[121][0], pathways[121][1], 6, 0, 2 * Math.PI);
                context.fillStyle = 'red';
                context.fill();
            } else {
                vertices = seg_1.concat(main_path,seg_2.reverse());
            }
        } else {
            if(secondary_flag){
                vertices = seg_1.concat(secondary_path,seg_2);
            } else {
                vertices = seg_1.concat(seg_2);
            }
        }
    }

    /*
    *   Calculate the extra points for animation, and draw the animation
    */
    if(secondary_vertices.length == 0){
        points = calcWaypoints(vertices);
        pre.push(points);
    } else {    
        points = calcWaypoints(vertices);
        secondary_points = calcWaypoints(secondary_vertices);
        pre.push(points, secondary_points);
    }
    arr.push([context,pre]);
    console.log(arr);
    resolve();
});
}

draw_marker在这里

function draw_marker(context, source, desti, isFirst, isLast) {
return new Promise(function(resolve) {
    /*
     * Get the point number of the point on the path that the source and destination connect to
     */

    var start = string_to_point[source];
    var finish = string_to_point[desti];

    /*
     *   Marker 
     */
    if (isFirst) {
        var marker1 = new Image();
        marker1.onload = function(){
            marker1._x = point_coord[start[0]][0]-1;
            marker1._y = point_coord[start[0]][1]-44;
            context.drawImage(marker1, marker1._x, marker1._y,marker1.width,marker1.height);
        };
        marker1.src = "images/map_pin.png";
    } else {
        context.fillStyle = 'green';
        context.beginPath();
        context.arc(point_coord[start[0]][0], point_coord[start[0]][1], 8, 0, 2 * Math.PI);

        context.strokeStyle = "green";
        context.stroke();
        context.fill();
    }
    if (isLast) {
        /*var marker2 = new Image();
        marker2.onload = function(){
            marker2._x = point_coord[finish[0]][0]-15;
            marker2._y = point_coord[finish[0]][1]-22;
            context.drawImage(marker2, marker2._x, marker2._y,marker2.width,marker2.height);
        };
        marker2.src = "images/x_marks.png";*/
    } else {
        context.fillStyle = 'red';
        context.beginPath();
        context.arc(point_coord[finish[0]][0], point_coord[finish[0]][1], 6, 0, 2 * Math.PI);

        context.strokeStyle = "#ff0000";
        context.stroke();
        context.fill();
    }
    resolve();
});
}

wrap在这里

function wrap(arr){
console.log("in wrap");
var getAnimation = function(context, lines){
    console.log("Get animation");
    console.log(lines);
    return new Promise(function(resolve) {
        context.beginPath();
        lines.reduce((a, c) => a.then(() => animate(context,c)), Promise.resolve());
        resolve();
    });
};  
arr.reduce((a,c) => a.then(() => getAnimation(c[0],c[1])),Promise.resolve());
}

animate在这里

var animate = function(context, p){
return new Promise(function(resolve) {
    console.log("in animate");
    var t = 1;
    context.lineCap = "round";
    context.lineWidth = 5;
    //context.strokeStyle = "#ff0000";
    context.strokeStyle = "#ff3c3c";
    //context.strokeStyle = "#f38f1d";
    var runAnimation = function(){
        if(t<p.length){
            console.log("running animation");
            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 {
            console.log("run animation resolved");
            resolve()
        }
    };
    runAnimation();
});
}

目标是根据需要运行get_pathdraw_markers的许多组合,然后运行wrap,后者又调用animate。每个animate都需要在下一个开始之前完成

我该如何做到这一点?

谢谢。如果需要更多细节,请告诉我

答案

如果目标javascript环境支持,您可以使用async/await。如果没有,你可以实现像Babel这样的编译器并以这种方式使用它。

如果您不想走那条路,那么Bluebird是一个Promise库,允许您使用Promise.map选项调用{ concurrency: 1 }。这将按顺序调用promise。

以上是关于返回promises的Javascript顺序函数的主要内容,如果未能解决你的问题,请参考以下文章

使用promise,JavaScript时函数不返回值

每个循环中的有序 JavaScript Promise

promise async/await

复杂承诺返回链中的承诺 catch() 顺序

javaScript-promise

ES6 Promises/在多个 Promise 完成后调用一个函数(不能使用 Promises.all)[重复]