J'ai quelques usines angulaires pour faire des appels ajax vers des services Web ASP.NET .asmx hérités comme ceci:
module.factory('productService', ["$http",
function ($http) {
return {
getSpecialProducts: function (data) {
return $http.post('/ajax/Products.asmx/GetSpecialProducs', data);
}
}
} ]);
Je teste sur un réseau local, donc les temps de réponse sont "trop" bons. Existe-t-il un moyen judicieux de retarder quelques secondes le $ http de l'appel pour simuler une mauvaise connexion?
Ou dois-je emballer tous les appels aux méthodes d'usine dans un délai d'attente de $?
$timeout(function() {
productService.getSpecialProducs(data).success(success).error(error);
}, $scope.MOCK_ajaxDelay);
Question interessante!
Comme vous l'avez dit vous-même, $timeout
est le choix le plus logique pour un appel différé. Au lieu d'avoir des appels $timeout
partout, vous pouvez utiliser un intercepteur de réponse qui enveloppe la promesse $http
dans une promesse $timeout
, comme indiqué de manière conceptuelle dans la documentation de $http
, et enregistrez-la dans l'un de vos blocs de configuration. Cela signifie que tous les appels $http
sont affectés par le délai $timeout
. Quelque chose dans le genre de:
$httpProvider.interceptors.Push(function($timeout) {
return {
"response": function (response) {
return $timeout(function() {
return response;
}, 2500);
}
};
});
En prime, pour "simuler une mauvaise connexion?", Vous pouvez également refuser ou ne rien faire au hasard. Heh heh heh.
Le nouvel émulateur de périphérique Chrome possède une fonction de limitation de réseau:
Pour vous y rendre: Dans Google Chrome, appuyez sur F12 pour ouvrir les outils de développement. Puis, dans le coin supérieur gauche, cliquez sur l’icône "Basculer en mode appareil" (à gauche du menu "Eléments").
Développer plus sur la réponse de @stevuu
responseInterceptors
semble être obsolète (à partir de 1.2.20) J'ai modifié le code pour fonctionner sur le mécanisme interceptors
:
$httpProvider.interceptors.Push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 2300);
return defer.promise;
}
};
});
Vous pouvez utiliser le service $ q pour le modèle defer (). Promise:
function someFunction(MOCK_ajaxDelay) {
var deferred = $q.defer();
$http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(function(response) {
$timeout(function() {deferred.resolve({ success: true, response: response })}, MOCK_ajaxDelay);
}).error(function() {
$timeout(function() {deferred.resolve({ success: true, response: response } }, MOCK_ajaxDelay);
});
return deferred.promise;
}
someService.someFunction(500).then(function(data) {
if (data.success) {
$scope.items = data.response.d;
}
});
Mais si vous êtes vraiment des simulacres de tests, la meilleure solution consiste à examiner ngMock: http://docs.angularjs.org/api/ngMock . $ HttpBackend
Tandis que @ stevuu answer est correct, la syntaxe a été modifiée dans les nouvelles versions d'AngularJS depuis lors. La syntaxe mise à jour est la suivante:
$httpProvider.interceptors.Push(["$q", "$timeout", function ($q, $timeout) {
function slower(response) {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(response);
}, 2000);
return deferred.promise;
}
return {
'response': slower
};
}]);
Vous pouvez y parvenir en utilisant l'API de promesse associée à un délai d'attente de $. La fonction $ http.post renvoie une promesse à partir de laquelle vous pouvez appeler .success et .error (ce sont des méthodes spécifiques à http). Cette promesse est résolu lorsque la demande http est terminée. Si vous créez votre propre promesse, vous pouvez lui imposer un délai de 2 secondes, puis résoudre le problème une fois la requête http terminée:
module.factory('productService', function ($http, $q, $timeout) {
return {
getSpecialProducts: function (data) {
var defer = $q.defer();
$http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(
function(data) {
// successful http request, resolve after two seconds
$timeout(function() {
defer.resolve(data);
}, 2000)
}).error(function() {
defer.reject("Http Error");
})
return defer.promise;
}
}
});
Mais notez que vous devrez utiliser la fonctionnalité promise.then(successCallback, errorCallback)
, autrement dit, vous ne pourrez plus accéder aux en-têtes http, aux status & config à partir de vos contrôleurs/directives, à moins que vous ne les fournissiez explicitement à l'objet transmis à defer.resolve({})
.
Liens:
Si vous utilisez un service qui retourne une promesse, vous devriez alors mettre un return avant le $ timeout , car cela ne renvoie qu'une autre promesse.
return dataService.loadSavedItem({
save_id: item.save_id,
context: item.context
}).then(function (data) {
// timeout returns a promise
return $timeout(function () {
return data;
},2000);
});
J'espère que ça aide quelqu'un!
En réponse à l'aspect test de votre question, Fiddler a une fonction très utile qui vous aide lorsque vous devez simuler des retards:
La fonctionnalité de répondeur automatique de Fiddler est extrêmement utile pour tester JS qui implique de nombreuses requêtes http. Vous pouvez le configurer pour répondre avec des codes d'erreur http particuliers, des réponses de bloc, etc.