TypeError:无法读取未定义的属性"defaultPrevented"

Ale*_*x C 10 settimeout angularjs

我在进行以下测试时遇到此错误:

it('should call pauseAnimationInterval if in focus', inject(function(SearchBoxData, intervalManager, $timeout){
  SearchBoxData.init_array = [];
  SearchBoxData.inFocus = true;
  SearchBoxData.init(intervalManager);
  console.log(intervalManager.pauseTimeout);
  console.log(intervalManager.pauseTimeoutTime);
  console.log($timeout);
  $timeout.flush(intervalManager.pauseTimeoutTime+1);
  expect(rootScope.$broadcast).toHaveBeenCalledWith('onPauseInterval', intervalManager.loopIndex);
}));
Run Code Online (Sandbox Code Playgroud)

它打破$timeout.flush(intervalManager.pauseTimeoutTime+1); $ timeout方法在intervalManager.pauseAnimationInterval()里面调用SearchBoxData.init(intervalManager):

intervalManager.pauseAnimationInterval = function (){

  intervalManager.safeCancel(intervalManager.continueInterval);
  intervalManager.safeCancel(intervalManager.initInterval);
  intervalManager.initInterval = null;
  intervalManager.continueInterval = null;

  intervalManager.pauseTimeout = $timeout(function () {
    if(intervalManager.inFocus === true){
      intervalManager.loopIndex += 1;
      if(intervalManager.loopIndex >= intervalManager.maxLoopIndex){
        intervalManager.loopIndex = 0;
      }
      $rootScope.$broadcast("onPauseInterval", intervalManager.loopIndex);
      intervalManager.continueAnimationInterval();
    }else{
      // Important condition: retry after the timeout if no focus
      // main reason of glitch
      intervalManager.pauseAnimationInterval();
    }
  }, intervalManager.pauseTimeoutTime);

};
Run Code Online (Sandbox Code Playgroud)

我之前没有收到这个错误,我不确定我做错了什么.

更新:这是一个带有未限制版本的angularJS的堆栈跟踪:

at /Users/foo/projects/bar/vendor/assets/javascripts/angular.js:9268:88
at Scope.$eval (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:11986:28)
at Scope.$digest (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:11812:31)
at Scope.$apply (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:12092:24)
at Object.fn (/Users/foo/projects/bar/vendor/assets/javascripts/angular.js:13627:36)
at Function.self.defer.flush (/Users/foo/projects/bar/spec/javascripts/lib/angular/angular-mocks.js:126:32)
at Function.$delegate.flush (/Users/foo/projects/bar/spec/javascripts/lib/angular/angular-mocks.js:1689:20)
at null.<anonymous> (/Users/foo/projects/bar/spec/javascripts/unit/services/searchboxdata_service_spec.js:71:16)
Run Code Online (Sandbox Code Playgroud)

更新2:我追溯到注射SearchBoxData工厂.我不确定它有什么问题.每当我创建$ timeout实例并使用flush方法时,只需注入它就会导致错误.

更新3:我注意到如果我在其中一个依赖项中注入$ location或$ route(间接的,它发生在我到处使用的一些基本服务),就会发生这种情况.

更新4:这是一个重现它的plunker!http://plnkr.co/edit/7XweXI?p=info

chr*_*lsa 31

$ broadcast()'或$ emit()'的范围事件是同步的,并在事件对象完成时返回它们.

Angular中的一些内容取决于返回的事件对象,例如ngRoute.

所以你可以做的就是andCallThrough()在创建你的间谍时简单地添加它,这样它就可以调用原始函数并产生一个返回值.

或者,如果您不想使用真正的$ broadcast,您可以使用andCallFake()提供可以返回任何所需内容的假函数.

例:

beforeEach(function(){
  module('MyApp');
  inject(function($injector){
    rootScope = $injector.get('$rootScope');
    spyOn(rootScope,'$broadcast').andCallThrough(); // will prevent the reference error
  })
});
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在Jasmine 2.0及更高版本中,语法为`and.callThrough();` (12认同)
  • 非常感谢@chronicsalsa,这个问题困扰了我好几天. (2认同)