AngularJS defer error: Argument 'fn' is not a function, got Object

Phil Pastorek picture Phil Pastorek · Apr 22, 2013 · Viewed 52k times · Source

I'm attempting to make my app gather the data before changing the route, as shown on many a video from John Lindquist: http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp

I have it all hooked up, but when it's time for the deferred object to resolve, i get the error:

Error: Argument 'fn' is not a function, got Object
at assertArg (http://localhost:9000/components/angular/angular.js:1019:11)
at assertArgFn (http://localhost:9000/components/angular/angular.js:1029:3)
at annotate (http://localhost:9000/components/angular/angular.js:2350:5)
at invoke (http://localhost:9000/components/angular/angular.js:2833:21)
at Object.instantiate (http://localhost:9000/components/angular/angular.js:2874:23)
at http://localhost:9000/components/angular/angular.js:4759:24
at <error: illegal access>
at Object.Scope.$broadcast (http://localhost:9000/components/angular/angular.js:8261:28)
at http://localhost:9000/components/angular/angular.js:7417:26
at wrappedCallback (http://localhost:9000/components/angular/angular.js:6797:59) angular.js:5704

My code looks like this:

Route -

angular.module( 'saApp' )
.config( function ( $routeProvider, $locationProvider ) {
    $routeProvider
        .when( '/dashboard', {
            templateUrl: 'views/dashboard/dashboard.html',
            controller: Dashboard,
            resolve: Dashboard.resolve
        } 
});

controller -

var Dashboard = angular.module( 'saApp' ).controller(
    function ( $scope, dataset ) {
            $scope.data = dataset;
    } );

Dashboard.resolve = {
  dataset: function ( $q, DBFactory ) {

    console.log("dataset enter")
    var deferred = $q.defer();

    DBFactory.get( {noun: "dashboard"},
        function ( data ) {
            console.log("resolving");
            deferred.resolve( data );
        } );

    console.log("promise");
    return deferred.promise;
  }
}

On run, it executes the resolve, the DBFactory resource goes, comes back and everything works up until the actual "deferred.resolve(data);" which is where then i get the error pasted above. If i comment that one line out, of course i get no page, but i also get no error.

The contents of data, coming back from DBFactory is a JSON object, which is what is expected, and shown in all the examples i've seen online and videos.

using:

AngularJS 1.0.6

Thoughts? Thanks for all your help.

UPDATE:

It seems the way i was using my routes and defining the controller with the namespace:

var Dashboard = angular.module( 'saApp' ).controller()

was to blame for this. When i simply use a standard function declaration:

function DashboardCtrl($scope, dataset) {
  $scope.data = dataset;
}

it satisfies the "looking for function, got object" error. The weird thing was i changed to using it as an object "var DashboardCtrl = angular.module('saApp').controller()" or even what i had it to prior to that from the yeoman generator, and specified in the angularjs docs of:

angular.module( 'saApp' )
.controller( 'DashboardCtrl', function ( $scope, dataset ) {});

with a route of:

.when( '/dashboard', {
            templateUrl: 'views/dashboard/dashboard.html',
            controller: 'DashboardCtrl'
        } )

wouldn't work.

Answer

Kath picture Kath · Dec 26, 2013

I had this error many times and finally found the perfect and simple solution. Just put your controller name in the 'when' construction into quotes like this:

.when( '/dashboard', {
    templateUrl: 'views/dashboard/dashboard.html',
    controller: 'Dashboard',
    resolve: Dashboard.resolve
}

instead of

.when( '/dashboard', {
    templateUrl: 'views/dashboard/dashboard.html',
    controller: Dashboard,
    resolve: Dashboard.resolve
}