$digest
ダイジェスト サイクル中にまたはを手動で呼び出す$apply
と、「$digest は既に進行中です」というエラーが発生することはわかっていますが、なぜここでエラーが発生するのかわかりません。
これは をラップするサービスの単体テストです。この$http
サービスは十分に単純で、サーバーへの重複呼び出しを防止するだけでなく、呼び出しを実行しようとするコードが期待どおりのデータを取得できるようにします。
angular.module('services')
.factory('httpService', ['$http', function($http) {
var pendingCalls = {};
var createKey = function(url, data, method) {
return method + url + JSON.stringify(data);
};
var send = function(url, data, method) {
var key = createKey(url, data, method);
if (pendingCalls[key]) {
return pendingCalls[key];
}
var promise = $http({
method: method,
url: url,
data: data
});
pendingCalls[key] = promise;
promise.then(function() {
delete pendingCalls[key];
});
return promise;
};
return {
post: function(url, data) {
return send(url, data, 'POST');
},
get: function(url, data) {
return send(url, data, 'GET');
},
_delete: function(url, data) {
return send(url, data, 'DELETE');
}
};
}]);
単体テストも非常に単純で$httpBackend
、リクエストを期待するために使用します。
it('does GET requests', function(done) {
$httpBackend.expectGET('/some/random/url').respond('The response');
service.get('/some/random/url').then(function(result) {
expect(result.data).toEqual('The response');
done();
});
$httpBackend.flush();
});
done()
これは、「$digest already in progress」エラーで呼び出されるとすぐに爆発します。理由がわかりません。done()
このようなタイムアウトでラップすることでこれを解決できます
setTimeout(function() { done() }, 1);
つまりdone()
、 $digest が完了した後にキューに入れられて実行されますが、それで問題が解決する間、私は知りたいです
- そもそもAngularがダイジェストサイクルにあるのはなぜですか?
done()
呼び出しによってこのエラーが発生するのはなぜですか?
Jasmine 1.3 でまったく同じテストをグリーンで実行しました。これは、Jasmine 2.0 にアップグレードし、新しい async-syntax を使用するようにテストを書き直した後にのみ発生しました。