简体   繁体   中英

Testable method for calling global javascript functions in angularjs controllers

Very Global Description

You have functions that must exist in the global scope. You want a way to encapsulate the functionality of these functions in a dependency injectable way so they are more testable. What is the correct way to do this?

Somewhat Specific Description

I have a situation where I have an existing javascript library that uses a lot of variables and function in the global scope. The library is a SCORM engine and part of the standard dictates that the functions must be available in the global scope (so user created content can access them).

However, there are a couple of places in various controllers that I must call them as well. At the moment I an just calling them, but this makes testing those lines difficult and seems to violate the angular mindset in general.

Plnkr

A plunk just illustrating how things are now

var globalVariable = 1;

function globalFunction(){
  return "cats";
}

var app = angular.module('plunker', []);

app.controller('MainCtrl', [ '$scope', function($scope) {
  $scope.name = 'World';
  $scope.cats = globalFunction(); //This line is hard to test and makes me feel dirty.
}]);

A plunk that wraps the function in a factory (maybe what is recommended in comments?)

var globalVariable = 1;

function globalFunction(){
  return "cats";
}

var app = angular.module('plunker', []);

app.factory('angularFriendly', function(){
  this.globalFunction = globalFunction;
  return this;
});

app.controller('MainCtrl', ['$scope', 'angularFriendly',
  function($scope, angularFriendly) {
    $scope.name = 'World';
    $scope.cats = angularFriendly.globalFunction();
  }
]);

This is more or less what I mean in my original comment when I said I considered wrapping it in a service. I make the function injectable (which is good and is much more testable) but I am not sure it is good practice (because I have just moved the difficult to test code to a different place).

I prefer wrapping 3rd party non-Angular applications into value objects (which is functionally the same as using a factory and immediately calling it prior to injection, which feels cleaner).

var globalVariable = 1;

function globalFunction(){
  return "cats";
}

var app = angular.module('plunker', []);
app.value('external', globalFunction);

app.controller('MainCtrl', ['$scope', 'external',
  function($scope, external) {
    $scope.name = 'World';
    $scope.cats = external();  // Treat the dependency as a service to resolve into the scope
  }
]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM