angularjs + requirejs + dependency in resolve

2019-02-20 04:01发布

问题:

How I can correct inject dependency P48Wallet in resolve for $routeProvider?

app.js

'use strict';

define(
[
    'angularAMD',
    'angular-route',
    'angular-animate'
],
function (angularAMD) {

var app = angular.module('FilmOrder', ['ngRoute', 'ngAnimate']);

app.config(['$routeProvider', function($routeProvider){

    $routeProvider
        .when('/',
            angularAMD.route({
                templateUrl: 'static/js/application/views/main.html',
                controller: 'application/controllers/Main',
                resolve: {
                     films:
                     require(['application/services/P48Wallet', function(P48Wallet) {
                         return P48Wallet.getUserData();
                     }])
                }
            })
        )

        .when('/success',
                angularAMD.route({
                templateUrl: 'static/js/application/views/success.html',
                controller: 'application/controllers/Success'
            })
        )

        .otherwise({redirectTo: '/'});
    }]);

    angularAMD.bootstrap(app);

    return app;
});

=========================================================

P48Wallet.js

'use strict';

define(['application/app', 'application/services/Http'], function(app) {

    return app.factory('P48Wallet', function(Http) {

        this.getUserData = function() {
            return Http.post('?action=get_data');
        };

        return this;
    });
});

=========================================================

I receive error:

Error: [$injector:unpr] http://errors.angularjs.org/undefined/$injector/unpr?p0=dProvider%20%3C-%20d

回答1:

2 problems that I can see:

  1. angularAMD.route sets the resolve property so it is overwriting the resolve that you are setting up.
  2. return app.factory expect an object to be return and not this

What you should be doing is define the P48Wallet as a factory/service and then add it to the dependency to your Main controller. For example:

application/services/P48Wallet.js

EDIT: Adding feature to cache the returned data from POST per comment.

define(['application/app', 'application/services/Http'], function(app) {
    app.register.service('P48Wallet', function(Http, $q) {
        var priv_data;

        // Assuming that your Http works the same way as $http
        this.getUserData = function() {
            var d = $q.defer();

            if (priv_data) {
                // Return cached value
                d.resolve(priv_data);
            } else {
                Http.post('?action=get_data')
                .then(function (data) {
                    priv_data = data;
                    d.resolve(data);
                })
                .catch(function (error) {
                    d.reject(error);
                });
            }
        };

        return d.promise;
    });
});

application/controllers/Main.js

define(['application/app', 'application/services/P48Wallet'], function (app) {
    app.register.controller("MainController", [
        '$scope', 'P48Wallet', function ($scope, P48Wallet) { ... }
    ]);
});

application/app.js

// Keeping everything the same except
angularAMD.route({
    templateUrl: 'static/js/application/views/main.html',
    controllerUrl: 'application/controllers/Main',
    controller: 'MainController'
})

Here is angularAMD's documentation on how to setup the route to lazy load controllers:

https://github.com/marcoslin/angularAMD#on-demand-loading-of-controllers