当前位置: 首页 > 面试题库 >

在angularjs中的诺言上设置超时处理程序

巩俊远
2023-03-14
问题内容

我正在尝试在控制器中设置超时,以便如果在250毫秒内未收到响应,它将失败。我将单元测试的超时设置为10000,这样就可以满足此条件,有人可以指出正确的方向吗?(编辑,我试图在不使用$
http服务的情况下实现这一点,我知道该服务提供超时功能)

(编辑-
我的其他单元测试失败了,因为我没有在它们上调用timeout.flush,现在我只需要在promiseService.getPromise()返回未定义的promise时获得超时消息即可。我删除了问题的早期代码)。

promiseService(promise是一个测试套件变量,允许我在应用之前对每个测试套件中的promise使用不同的行为,例如拒绝一个,另一个成功)

    mockPromiseService = jasmine.createSpyObj('promiseService', ['getPromise']);
    mockPromiseService.getPromise.andCallFake( function() {
        promise = $q.defer();
        return promise.promise;
    })

正在测试的控制器功能-

$scope.qPromiseCall = function() {
    var timeoutdata = null;
    $timeout(function() {
        promise = promiseService.getPromise();
        promise.then(function (data) {
                timeoutdata = data;
                if (data == "promise success!") {
                    console.log("success");
                } else {
                    console.log("function failure");
                }
            }, function (error) {
                console.log("promise failure")
            }

        )
    }, 250).then(function (data) {
        if(typeof timeoutdata === "undefined" ) {
            console.log("Timed out")
        }
    },function( error ){
        console.log("timed out!");
    });
}

测试(通常我在这里解决或拒绝诺言,但未设置它就是模拟超时)

it('Timeout logs promise failure', function(){
    spyOn(console, 'log');
    scope.qPromiseCall();
    $timeout.flush(251);
    $rootScope.$apply();
    expect(console.log).toHaveBeenCalledWith("Timed out");
})

问题答案:

首先,我想说你的控制器实现应该是这样的:

$scope.qPromiseCall = function() {

    var timeoutPromise = $timeout(function() {
      canceler.resolve(); //aborts the request when timed out
      console.log("Timed out");
    }, 250); //we set a timeout for 250ms and store the promise in order to be cancelled later if the data does not arrive within 250ms

    var canceler = $q.defer();
    $http.get("data.js", {timeout: canceler.promise} ).success(function(data){
      console.log(data);

      $timeout.cancel(timeoutPromise); //cancel the timer when we get a response within 250ms
    });
  }

您的测试:

it('Timeout occurs', function() {
    spyOn(console, 'log');
    $scope.qPromiseCall();
    $timeout.flush(251); //timeout occurs after 251ms
    //there is no http response to flush because we cancel the response in our code. Trying to  call $httpBackend.flush(); will throw an exception and fail the test
    $scope.$apply();
    expect(console.log).toHaveBeenCalledWith("Timed out");
  })

  it('Timeout does not occur', function() {
    spyOn(console, 'log');
    $scope.qPromiseCall();
    $timeout.flush(230); //set the timeout to occur after 230ms
    $httpBackend.flush(); //the response arrives before the timeout
    $scope.$apply();
    expect(console.log).not.toHaveBeenCalledWith("Timed out");
  })

演示

另一个例子promiseService.getPromise

app.factory("promiseService", function($q,$timeout,$http) {
  return {
    getPromise: function() {
      var timeoutPromise = $timeout(function() {
        console.log("Timed out");

        defer.reject("Timed out"); //reject the service in case of timeout
      }, 250);

      var defer = $q.defer();//in a real implementation, we would call an async function and 
                             // resolve the promise after the async function finishes

      $timeout(function(data){//simulating an asynch function. In your app, it could be
                              // $http or something else (this external service should be injected
                              //so that we can mock it in unit testing)
        $timeout.cancel(timeoutPromise); //cancel the timeout

         defer.resolve(data);
      });

      return defer.promise;
    }
  };
});

app.controller('MainCtrl', function($scope, $timeout, promiseService) {

  $scope.qPromiseCall = function() {

    promiseService.getPromise().then(function(data) {
      console.log(data); 
    });//you could pass a second callback to handle error cases including timeout

  }
});

您的测试类似于上面的示例:

it('Timeout occurs', function() {
    spyOn(console, 'log');
    spyOn($timeout, 'cancel');
    $scope.qPromiseCall();
    $timeout.flush(251); //set it to timeout
    $scope.$apply();
    expect(console.log).toHaveBeenCalledWith("Timed out");
  //expect($timeout.cancel).not.toHaveBeenCalled(); 
  //I also use $timeout to simulate in the code so I cannot check it here because the $timeout is flushed
  //In real app, it is a different service
  })

it('Timeout does not occur', function() {
    spyOn(console, 'log');
    spyOn($timeout, 'cancel');
    $scope.qPromiseCall();
    $timeout.flush(230);//not timeout
    $scope.$apply();
    expect(console.log).not.toHaveBeenCalledWith("Timed out");
    expect($timeout.cancel).toHaveBeenCalled(); //also need to check whether cancel is called
  })

演示



 类似资料:
  • Spring docs表示,需要手动为WebClient配置http客户机以设置超时:https://docs.Spring.io/Spring/docs/current/spring-framework-reference/web-reactive.html#webflux-client-builder-reactor-timeout。但是,由于WebClient返回反应单声道,所以可以(在AP

  • expire key seconds 单位是秒。返回1成功,0表示key已经设置过过期时间或者不存在。 如果想消除超时则使用persist key。如果希望采用绝对超时,则使用expireat命令。 ttl key 返回设置过过期时间的key的剩余过期秒数 -1表示没有设置过过期时间,对于不存在的key,返回-2。 pexpire key 毫秒数 设置生命周期。 pttl key 以毫秒返回生命

  • 问题内容: 我知道我可以每次设置超时: …但是我想设置一个全局超时来保持我的代码为DRY。 问题答案: UPDATED :$ http将不遵守默认设置,因为它在httpProvider中设置了超时(请参见注释)。可能的解决方法: https //gist.github.com/adnan-i/5014277 原始答案:

  • 问题内容: 情况 我有一个简单的python脚本来获取给定URL的HTML源: 有时,URL指向外部资源加载缓慢的页面(例如,视频文件或非常慢的广告内容)。 在完成请求之前,Webdriver将等待直到加载了这些资源。 注意:由于其他原因,我需要使用PhantomJS而不是或 问题 我想在PhantomJS资源加载上设置一个超时,以便如果资源加载时间太长,浏览器只会认为它不存在或其他原因。 这将允

  • 问题内容: 我正在尝试在使用http.request且没有运气的HTTP客户端上设置超时。到目前为止,我所做的是: 有什么提示吗? 问题答案: 现在可以使用option和相应的request事件:

  • 问题内容: Firefox总是加载动态图像,但是IE只是显示图像而没有任何动态动作。我需要做些什么改变? IE查看源代码中的JavaScript代码: 我正在使用Wicket框架,所以真正的Java代码是: 加载我的动态图像的html页面是: 问题答案: 解决了我的问题。可能对其他人有用: 回答: HTML源代码: HTML: