当$ http调用处于挂起状态时清除setTimeout

时间:2016-02-01 20:17:21

标签: javascript angularjs http settimeout angular-promise

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<script>
var canvas, ctx;
var blackhole;
var circle;
 var circles = new Array();
  var G = 6.67e-11, //gravitational constant
  pixel_G = G / 1e-11,
  c = 3e8, //speed of light (m/s)
  M = 12e31, // masseof the blackhole in kg (60 solar masses)
  pixel_M = M / 1e32
  Rs = (2 * G * M) / 9e16, //Schwarzchild radius 
  pixel_Rs = Rs / 1e3, // scaled radius 
  ccolor = 128;

  function update() {
   var pos, i, distance, somethingMoved = false;
   for (i = 0; i < circles.length; i++) {
      pos = circles[i].position;
   distance = Math.sqrt(((pos.x - 700) * (pos.x - 700)) + ((pos.y - 400) * (pos.y - 400)));
if (distance > pixel_Rs) {
  var delta = new Vector2D(0, 0);
  var forceDirection = Math.atan2(pos.y - 400, pos.x - 700);
  var evelocity = Math.sqrt((2 * pixel_G * pixel_M) / (distance * 1e-2));
  delta.x += Math.cos(forceDirection) * evelocity;
  delta.y += Math.sin(forceDirection) * evelocity;
  pos.x += delta.x;
  pos.y += delta.y;
  somethingMoved = true;
} else {
  var delta2 = new Vector (0,0);
  var forceDirection2 = Math.atan2(pos.y - 400, pos.x - 700);
  var g = (pixel_G*pixel_M)/(distance*distance*1e3);
  delta2.x += Math.cos(forceDirection2) * g;
  delta2.y += Math.sin(forceDirection2) *g;
  pos.x -= delta2.x;
  pos.y -= delta2.y;
  somethingMoved = true;   
  circles[i].color -= 0.50;
  if (pos.x = 700 && pos.y = 400){
  somethingMoved = false;

  }    
 }
 }
 if (somethingMoved) {
drawEverything();
requestAnimationFrame(update);
 };
}



 function drawEverything() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  blackhole.draw(ctx);
 for (var i = 0; i < circles.length; i++) {

    circles[i].draw(ctx);
    }
    }


function init() {
 canvas = document.getElementById("space");
 ctx = canvas.getContext('2d');
  blackhole = new Ball(pixel_Rs, {
x: 700,
y: 400
 }, 0);

for (var i = 0; i < 200; i++) {
var vec2D = new Vector2D(Math.floor(Math.random() * 1400),    Math.floor(Math.random() * 800));
circle = new Ball(5, vec2D, ccolor);
circles.push(circle);
 }
 drawEverything();
 requestAnimationFrame(update);
  }

   function Ball(radius, position, color) {
   this.radius = radius;
    this.position = position;
   this.color = color;
    }

  Ball.prototype.draw = function(ctx) {
  var c=parseInt(this.color);
  ctx.fillStyle = 'rgba(' + c + ',' + c + ',' + c + ',1)';
  ctx.beginPath();
  ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
  ctx.closePath();
  ctx.fill();
  };

function Vector2D(x, y) {
 this.x = x;
 this.y = y;
  }

function onClick (){
  canvas = document.getElementById ('space');
  ctx = canvas.getContext ('2d') 
  canvas.addEventListener ("mousedown", init, false)
  blackhole = new Ball (5, {
   x: 700,
   y: 400
  }, 0);
 blackhole.draw (ctx) ;                   

}  
window.onload = onClick;


</script>
 <style>
   body {
   background-color:#021c36 ;
    margin: 0px;}
  </style>
</head>
 <body>
 <canvas id = "space", width = "1400", height = "800">
 </canvas>
</body>
  </html>

当我要去不同的控制器时我确定我要取消所有超时但是问题是当$ http呼叫处于挂起状态并且我同时移动到不同的控制器时(超时没有被创建)直到我们得到响应)并且我无法取消控制器更改的超时,因为呼叫处于暂挂状态,我无法清除尚未创建的超时。

我该如何处理这种情况。什么是这个问题的最佳解决方案。

我已经完成了这个但是在错误部分我无法区分网络错误和取消超时,因为如果是网络错误我还需要调用setTimeout。

function getDBCounts() {
    $http.get('URL')
        .then(function (response){
            $scope.stats = response.data;
            $scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
         }, function () {
             $scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
         })
}


$scope.$on("$destroy", function () {
    clearTimeout($scope.getDBCountsTimeOut);
});

对于网络错误和超时,我将此作为回复:

$scope.canceler = $q.defer();
function getDBCounts() {
     $http
       .get(apiUri + '/backend/database/stats', {timeout: $scope.canceler.promise})
        .then(function (response){
              $scope.stats = response.data;
              $scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
          }, function (er, second) {
              $scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
          })
 }

$scope.$on("$destroy", function () {
   clearTimeout($scope.getDBCountsTimeOut);
    $scope.canceler.resolve();
});

现在我该如何解决这个问题。 提前谢谢。

1 个答案:

答案 0 :(得分:0)

这似乎是$http API的限制。我也希望您能从响应/错误中判断出请求是否超时。

我在这里看到的唯一方法是你没有取消承诺,但是当它被销毁时在范围内设置一个标志。然后,当范围已被销毁时,您根本不设置超时:

function getDBCounts() {
    $http.get('URL')
        .then(function (response){
            $scope.stats = response.data;
         })
         .finally(function() {
             if (!$scope.destroyed) {
                 $scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
             }
         })
}

$scope.$on("$destroy", function () {
    clearTimeout($scope.getDBCountsTimeOut);
    $scope.destroyed = true;
});

你的方法更好,并且是正确的&#34;办法。但是,似乎这是不可能的。

PS:如果您想做某事,无论承诺是否已被解决或拒绝,您应该使用finally(见上文)。请注意,在较旧的浏览器中(因此较旧的JS / ECMA-Script版本)finally是保留字。如果您想确保支持旧版浏览器,请按以下方式调用它:

$http.get(...)["finally"](function() {
})