0

I am trying to work things out with angularjs, dependency injections, factories and signalR hubs, but I get the error Unknown provider: personHubProvider <- personHub and I cannot figure out what is causing it.

My code is like this:

First I declare the module:

var ucp = angular.module('UCP', []);

which is used in the html tag by ng-app="UCP".

Then I do some configuration on the ucp module for the hub settings and creating a signalRHub factory to get the hubs without typing much of the same code:

ucp.config(function($routeProvider) {

    //Declaring routes, removed this part of code cause I think it hasn't to do
    //with the problem I got    

    $.support.cors = true;
    $.connection.hub.url = config.signalR.connectionURL;
    $.connection.hub.logging = config.signalR.logging;
    $.connection.hub.start();

}).factory('signalRHub', [function() {
      return {
          person: $.connection.Persons.server
      };
}]);

Then, I create another factory, that takes care of getting the data from the server:

ucp.factory('personHub', ['signalRHub', function(signalRHub) {
    return {
        get: function(onsuccess, onerror) {
            signalRHub.person.get()
                .done(function(persons) {
                    onsuccess(persons);
                })
                .fail(function(error) {
                    onerror(error);
                });
        }
    }
}]);

and this factory I inject in my controller so I can execute the call to get the data from the server and put it in the scope which provides to show the data in the browser:

ucp.controller('personController', ['$scope', 'personHub', function($scope, personHub){
    var self = this;

    $scope.init = function() {
        personHub.get(self.ongetsuccess, self.ongeterror);
    }

    self.ongetsuccess = function(persons) {
        $scope.persons = persons;
    };

    self.ongeterror = function(error) {

    };
}]);

When I open the webpage I get the error I mentioned before: Error: Unknown provider: personHubProvider <- personHub.

I think something goes wrong with creating the personHub factory service, which on his turn causes an Dependency Injection error for the controller. My question is, what is causing the error, am I doing something wrong with creating the personHub factory and if so, what am I doing wrong?

Cornelis
  • 1,729
  • 5
  • 23
  • 39
  • 1
    Be sure your factory is being setup before the controller is possibly used, I've personally smashed my services in with my controllers so that each file is a functional group of services first then controllers that generally rely on those services (possibly others as well). I don't see any errors in the factory definition as is, and if you're not seeing anything in the console aside from the error you show here I wouldn't be too suspect of it. You're correct though this is generally the error you will get for a service provider can't be found for some service you injected. – shaunhusain Aug 21 '13 at 14:42
  • Seems the factory isn't set up yet indeed before the controller is used which I don't get. In my index.html file loading the js file containing the factory is above loading the js file containing controller, yet the loading sequence on run time seems to be the other way around? Why is that. When I add the factory code into the same file as the controller code, I don't get the error anymore. Does this mean I cannot seperate this code by putting in 2 different files? Sounds weird to me if I couldn't. – Cornelis Aug 21 '13 at 19:15
  • I believe if you put a script tag in the head it loads asynchronously but in the body they load in order. I personally have been keeping my scripts in the head (a disadvantage here is that they will load before the page is rendered, I've varied this on projects, advantage being the scripts can run before the page is rendered, it's a toss up). I have my code separated into files but I also have a module per file then I have my main module depend on all the pieces, I'm not sure exactly how it's all loading honestly but it works. – shaunhusain Aug 21 '13 at 21:42
  • Some more on the topic here http://stackoverflow.com/questions/496646/how-does-the-location-of-a-script-tag-in-a-page-affect-a-javascript-function-tha and about manually starting up angular as opposed to having an ng-app directive http://docs.angularjs.org/guide/bootstrap Using CDN (cloud hosted js) helps as well since the domains won't be the same which means the two files per domain rule isn't as much of an issue, also in the end you can setup a build script for merging the js files and minifying etc. http://gruntjs.com/ – shaunhusain Aug 21 '13 at 21:45

1 Answers1

1

As I had stated in the comments I know this error occurs because the injected $provider isn't defined therefore it's reporting that there is nothing to provide said $provider. A $provider might be a factory, service, controller, or value (there's probably others I'm forgetting) and must be defined before it is referenced for an injection.

More on providers and injection here: https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection

The way I've been dealing with organizing code is by encapsulating most of the parts necessary for a given view into one js file. In that JS file I start off with a services section where I define a new module like:

angular.module("loginModule.services",[/*dependencies*/]).service("loginService", [/*dependencies*/function(){ return {get:function(){return "what up!"}};}]);

Then lower in the file I define my controllers like

angular.module("loginModule.controllers",[/*dependencies*/]).controller("LoginCtrl" ,["$scope", function($scope) { /* code here* /}]);

then at the bottom of the file

angular.module("loginModule", ["loginModule.services", "loginModule.controllers"]);

And finally in my mainApp.js (with the main ng-app module)

angular.module("mainApp", ["loginModule"]);

I've defined my script blocks in the head at the moment.

    <script type="text/javascript" src="components/loginModule.js"></script>
    <script type="text/javascript" src="mainApp.js"></script>

Also to note my loginModule actually depends on other services for which the javascript files come afterward. This doesn't seem to be an issue since the mainApp.js is being deferred until the end.

I just checked some of this in Chrome and it appears the JS files from my computer do load in order and as pairs (only two per domain at a time then when a response comes back the next request is fired). I also tried moving the script blocks from the head to the bottom of the HTML and I can't tell any difference (my laptop has an SSD and mostly local files so probably more appreciable in a production scenario).

shaunhusain
  • 19,630
  • 4
  • 38
  • 51