链接一系列异步调用(Chain a series of asynchronous calls)
我有一系列的异步操作
private void doSomething(){ get("/something", new Callback(){ void onComplete(String data){ updateUi(something, data); doSomethingElse(); } }); } private void doSomethingElse(){ get("/something/else", new Callback(){ void onComplete(String data){ updateUi(somethingElse, data); doYetAnotherThing(); } }); } private void doYetAnotherThing(){ get("/yet/another/thing", new Callback(){ void onComplete(String data){ updateUi(yetAnotherThing, data); allDone(); } }); }
这有几个问题:
- 由于每个回调都与“下一步”有内在联系,因此无法在其他地方重复使用任何回调
- 重新排序操作或插入其他操作是非直观的,并涉及到所有地方跳跃。
我已经看过以下选项来减轻这一点:
ExecuterService#invokeAll
- 我没有看到这个解决方案如何在没有阻塞的情况下使用。- RxJava--如果可以的话,我宁愿避免在我的应用程序中出现这种范式转变!
- 番石榴的
ListenableFutures
及其transform
方法。 我看到这在互联网螺母周围的少数地方提到,我真的不知道这将如何解决我的问题。所以,问题是:在Java中链接一系列异步调用的好模式是什么? 因为我需要一个适用于Android应用程序的解决方案,所以需要使用Java 7。
I have a series of asynchronous operations
private void doSomething(){ get("/something", new Callback(){ void onComplete(String data){ updateUi(something, data); doSomethingElse(); } }); } private void doSomethingElse(){ get("/something/else", new Callback(){ void onComplete(String data){ updateUi(somethingElse, data); doYetAnotherThing(); } }); } private void doYetAnotherThing(){ get("/yet/another/thing", new Callback(){ void onComplete(String data){ updateUi(yetAnotherThing, data); allDone(); } }); }
This suffers from few problems:
- Cannot reuse any of the callbacks elsewhere since each is intrinsically tied to the "next step"
- Re-ordering operations or inserting another operation is non-intuitive and involves jumping all over the place.
I have looked at the following options to mitigate this:
ExecuterService#invokeAll
- I don't see how this solution can be used without blocking.- RxJava - I would prefer to avoid such a paradigm shift in my application if I can!
- Guava's
ListenableFutures
and itstransform
method. I saw this referred to in few places around the interwebs nut I honestly don't see how this would solve my problem.So, the question is: What would be a good pattern to chain a series of asynchronous calls in Java? Looking for a solution that works with Java 7 since I need this for an Android app.
原文:https://stackoverflow.com/questions/26059300
更新时间:2022-01-26 13:01
最满意答案
这应该让你开始http://jsfiddle.net/0ao9oa7a/
- 获取所有记录的点
- 过滤出相近的点(我使用5个像素)
- 找出每对连续点的角度(atan2)
- 找出每对连续角度之间的绝对差异
- 在最大差异之前丢弃所有角度
- 平均剩余的角度(平均所有点矢量然后atan2回到一个角度)
码
function process(points) { if(points.length === 0) { txt = "Not enough points\n" + txt; return null; } // compress points, removing those that are too close together var newPoints = []; newPoints.push(points[0]); for(var i = 1; i < points.length; i++) { if(Math.sqrt(Math.pow(points[i].x - newPoints[newPoints.length - 1].x, 2) + Math.pow(points[i].y - newPoints[newPoints.length - 1].y, 2)) > 5) { newPoints.push(points[i]); } } points = newPoints; if(points.length < 2) { txt = "Not enough points\n" + txt; return null; } // get all of the angles var angles = []; for(var i=0; i < points.length - 1; i++) { var rad = Math.atan2(points[i + 1].y - points[i].y, points[i + 1].x - points[i].x); angles[i] = rad; txt += "x: " + (points[i].x|0) + " y: " + (points[i].y|0) + " x: " + (points[i+1].x|0) + " y: " + (points[i+1].y|0) + " [" + ((rad * 180 / Math.PI)|0) + "]" + "\n"; } txt += "\n"; // get all of the diffs between angles // save the index of the max diff var absDiffs = []; var maxDiff = -1; var maxDiffAngleIndex = -1; for(var i=0; i < points.length - 1; i++) { var delta = Math.abs(angles[i] - angles[i + 1]); if(delta >= maxDiff) { maxDiff = delta; maxDiffAngleIndex = i + 1; } } if(maxDiffAngleIndex == -1) { txt = "Angle: " + angles[0] + " : " + (angles[0] * 180 / Math.PI) + "\n" + txt; return angles[0]; } else if(maxDiffAngleIndex == angles.length - 1) { txt = "Angle: " + angles[angle.length - 1] + " : " + (angles[angles.length - 1] * 180 / Math.PI) + "\n" + txt; return angles[angles.length - 1]; } else { // find the average angle from the index to the end var sumX = 0; var sumY = 0; for(var i = maxDiffAngleIndex; i < angles.length; i++) { sumX += Math.cos(angles[i]); sumY += Math.sin(angles[i]); } var avgX = sumX / (angles.length - maxDiffAngleIndex); var avgY = sumY / (angles.length - maxDiffAngleIndex); // var avgAngle = Math.atan2(avgY, avgX); txt = "Angle: " + avgAngle + " : " + (avgAngle * 180 / Math.PI) + "\n" + txt; return avgAngle; } }
This should get you started http://jsfiddle.net/0ao9oa7a/
- Get all of the recorded points
- Filter out points that are close together (I use 5 pixels)
- Find the angles of each consecutive pair of points (atan2)
- Find the absolute differences between each consecutive pair of angles
- Throw away all of the angles before the max difference
- Average the remaining angles (average all point vectors then atan2 back into an angle)
Code
function process(points) { if(points.length === 0) { txt = "Not enough points\n" + txt; return null; } // compress points, removing those that are too close together var newPoints = []; newPoints.push(points[0]); for(var i = 1; i < points.length; i++) { if(Math.sqrt(Math.pow(points[i].x - newPoints[newPoints.length - 1].x, 2) + Math.pow(points[i].y - newPoints[newPoints.length - 1].y, 2)) > 5) { newPoints.push(points[i]); } } points = newPoints; if(points.length < 2) { txt = "Not enough points\n" + txt; return null; } // get all of the angles var angles = []; for(var i=0; i < points.length - 1; i++) { var rad = Math.atan2(points[i + 1].y - points[i].y, points[i + 1].x - points[i].x); angles[i] = rad; txt += "x: " + (points[i].x|0) + " y: " + (points[i].y|0) + " x: " + (points[i+1].x|0) + " y: " + (points[i+1].y|0) + " [" + ((rad * 180 / Math.PI)|0) + "]" + "\n"; } txt += "\n"; // get all of the diffs between angles // save the index of the max diff var absDiffs = []; var maxDiff = -1; var maxDiffAngleIndex = -1; for(var i=0; i < points.length - 1; i++) { var delta = Math.abs(angles[i] - angles[i + 1]); if(delta >= maxDiff) { maxDiff = delta; maxDiffAngleIndex = i + 1; } } if(maxDiffAngleIndex == -1) { txt = "Angle: " + angles[0] + " : " + (angles[0] * 180 / Math.PI) + "\n" + txt; return angles[0]; } else if(maxDiffAngleIndex == angles.length - 1) { txt = "Angle: " + angles[angle.length - 1] + " : " + (angles[angles.length - 1] * 180 / Math.PI) + "\n" + txt; return angles[angles.length - 1]; } else { // find the average angle from the index to the end var sumX = 0; var sumY = 0; for(var i = maxDiffAngleIndex; i < angles.length; i++) { sumX += Math.cos(angles[i]); sumY += Math.sin(angles[i]); } var avgX = sumX / (angles.length - maxDiffAngleIndex); var avgY = sumY / (angles.length - maxDiffAngleIndex); // var avgAngle = Math.atan2(avgY, avgX); txt = "Angle: " + avgAngle + " : " + (avgAngle * 180 / Math.PI) + "\n" + txt; return avgAngle; } }
相关问答
更多-
TCP/IP模型是一个________。[2023-10-02]
a -
this.getAngle = function(){ var angle = Math.atan2(this.y, this.x); //radians // you need to devide by PI, and MULTIPLY by 180: var degrees = 180*angle/Math.PI; //degrees return (360+Math.round(degrees))%360; //round number, avoid decima ...
-
下列中不属于面向对象的编程语言的是?[2022-05-30]
a -
这应该让你开始http://jsfiddle.net/0ao9oa7a/ 获取所有记录的点 过滤出相近的点(我使用5个像素) 找出每对连续点的角度(atan2) 找出每对连续角度之间的绝对差异 在最大差异之前丢弃所有角度 平均剩余的角度(平均所有点矢量然后atan2回到一个角度) 码 function process(points) { if(points.length === 0) { txt = "Not enough points\n" + txt; retu ...
-
由于您的值在区间[0 360]中始终是标准化的,因此这不应该太难。 您只需要区分两种不同的情况: angle < touchAngle angle > touchAngle 在第一种情况下,我们想要逆时针旋转,因此更新必须是angle =+ 1 (假设您希望每个更新周期转为1)。 在第二种情况下,我们想要顺时针转动,因此更新应该是angle -= 1 。 问题是这并不总是最短的旋转方式。 例如,如果: angle == 359 touchAngle == 1 我们不想一直使用358,357,356 .. ...
-
角度方向(Direction to angle)[2022-11-02]
您需要相对于某个点定义旋转。 目前你正在相对于屏幕的角落这样做,它只会给你90度,可能不是你想要的。 您可能希望相对于精灵的位置或相对于屏幕中心的旋转,例如 // define centre of screen const int Y0 = SCREEN_HEIGHT / 2; const int X0 = SCREEN_WIDTH / 2; // get rotation angle of mouse location relative to centre of screen double rotate ... -
听起来你想要使用UIPanGestureRecognizer 。 与滑动识别器不同,它被称为连续但具有不同的状态,因此您可以做一些简单的事情,只需处理开始和结束状态。 文档: https : //developer.apple.com/library/ios/documentation/UIKit/Reference/UIPanGestureRecognizer_Class/index.html Sounds like you want to use a UIPanGestureRecognizer ins ...
-
使用二维向量。 像这样的东西: movement = new Vector2D(); if (moveLeft) movement.x += 1; if (moveRight) movement.x -= 1; if (moveUp) movement.y -= 1; if (moveDown) movement.y += 1; movement.normalize(); // Caps the movement vector at a length of one, even when it's a ...
-
计算角度变化量时,您总是使用atan2 ,然后进行归一化。 原因是,例如acos是一个域-1 ... 1的函数; 如果输入绝对值(因为近似值)大于1,即使很明显在这种情况下你会喜欢0或PI的角度,函数也会失效。 此外, acos无法测量整个范围-PI..PI,您需要使用显式符号测试来查找正确的象限。 相反atan2只有奇点位于(0, 0) (当然,计算角度没有意义),其codomain是整圆-PI ... PI。 这是C ++中的一个例子 // Absolute angle 1 double a1 = at ...
-
如果我正确理解你的问题,你正在寻找一个方向矢量? 如果这是一个正确的理解,你可以做这样的事情: // Declared as fields, so they will be reused Vector2 position = new Vector2(); Vector2 velocity = new Vector2(); Vector2 movement = new Vector2(); Vector2 touch = new Vector2(); Vector2 dir = new Vector2(); ...