gpt4 book ai didi

javascript - 在 AngularJS 中为 Promise 设置超时处理程序

转载 作者:行者123 更新时间:2023-12-02 23:45:09 25 4
gpt4 key购买 nike

我正在尝试在 Controller 中设置超时,以便如果在 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;
})

正在测试的 Controller 功能 -

$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!");
});
}

测试(通常我会解决或拒绝此处的 promise ,但如果不设置它,我会模拟超时)

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

最佳答案

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

$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");
})

DEMO

另一个使用 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
})

DEMO

关于javascript - 在 AngularJS 中为 Promise 设置超时处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22994871/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com