javascript - 返回承诺的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_path
目标是根据需要运行和的任意多个组合draw_markers
,然后运行wrap
,然后调用animate
. 每个都animate
需要在下一个开始之前完成
我该如何做到这一点?
谢谢你。如果需要更多详细信息,请告诉我
解决方案
如果目标 JavaScript 环境支持,您可以使用async/await 。如果没有,您可以实现像 Babel 这样的编译器并以这种方式使用它。
如果您不想走那条路,可以使用 Bluebird,这是一个 Promise 库,允许您Promise.map
使用{ concurrency: 1 }
选项进行调用。这将按顺序调用承诺。
推荐阅读
- sql - Netezza 一年中第 n 周的第一天
- sql - 为什么存储过程需要超过 50 秒才能检索?
- google-apps-script - 修改函数以下载工作表
- hibernate - 当父->子关系未映射时,如何通过子查询父
- javascript - 由于 CORS 在复杂的服务器情况下访问 XMLHttpRequest
- amazon-cognito - 为 cognito 定义每个用户的自定义范围
- java - Java ProcessBuilder 每次调用新控制台?
- linux - 开关中断时 D lang 中的随机分段错误
- dart - Dart:快照与 AOT
- r - 如何在 R 中生成具有条件的随机数?