加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angularjs – 在Jasmine 2.0的异步测试中获取“$digest already

发布时间:2020-12-17 08:39:41 所属栏目:安全 来源:网络整理
导读:我知道调用$ digest或$应用程序手动在一个摘要周期将导致一个“$ digest已经在进行”错误,但我不知道为什么我得到它在这里。 这是一个单元测试的服务包装$ http,该服务很简单,它只是防止对服务器重复调用,同时确保尝试执行调用的代码仍然获得预期的数据
我知道调用$ digest或$应用程序手动在一个摘要周期将导致一个“$ 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,method) {
            var key = createKey(url,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,'POST');
            },get: function(url,'GET');
            },_delete: function(url,'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已经在进行”错误。我不知道为什么。我可以解决这个通过包裹done()在这样的超时

setTimeout(function() { done() },1);

这意味着done()将排队,并运行在$ digest完成后,但同时解决我的问题,我想知道

>为什么Angular在摘要周期中首先?
>为什么调用done()触发这个错误?

我有与Jasmine 1.3运行绿色的完全相同的测试,这只发生在我升级到Jasmine 2.0和重写了测试使用新的异步语法。

$ httpBacked.flush()实际上启动并完成一个$ digest()循环。我花了一整天昨天挖掘ngResource和角模拟的源头到这底部,仍然不完全理解它。

据我所知,$ httpBackend.flush()的目的是完全避免上面的异步结构。换句话说,它的语法(‘should do something’,function(done){});和$ httpBackend.flush()不能很好地在一起玩。 .flush()的目的是推送待处理的异步回调,然后返回。它就像一个大的完成包装你的所有异步回调。

所以如果我理解正确(它现在适用于我)正确的方法是删除done()处理器时使用$ httpBackend.flush():

it('does GET requests',function() {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    service.get('/some/random/url').then(function(result) {
        expect(result.data).toEqual('The response');
    });
    $httpBackend.flush();
});

如果添加console.log语句,您会发现所有的回调在flush()周期中始终发生:

it('does GET requests',function() {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    console.log("pre-get");
    service.get('/some/random/url').then(function(result) {
        console.log("async callback begin");
        expect(result.data).toEqual('The response');
        console.log("async callback end");
    });
    console.log("pre-flush");
    $httpBackend.flush();
    console.log("post-flush");
});

然后输出将是:

pre-get

pre-flush

async callback begin

async callback end

post-flush

每次。如果你真的想看到它,抓住范围,看看范围。$$阶段

var scope;
beforeEach(function(){
    inject(function($rootScope){
        scope = $rootScope;
    });
});
it('does GET requests',function() {
    $httpBackend.expectGET('/some/random/url').respond('The response');

    console.log("pre-get "+scope.$$phase);
    service.get('/some/random/url').then(function(result) {
        console.log("async callback begin "+scope.$$phase);
        expect(result.data).toEqual('The response');
        console.log("async callback end "+scope.$$phase);
    });
    console.log("pre-flush "+scope.$$phase);
    $httpBackend.flush();
    console.log("post-flush "+scope.$$phase);
});

你会看到输出:

pre-get undefined

pre-flush undefined

async callback begin $digest

async callback end $digest

post-flush undefined

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读