AngularJS - 使用异步调用在两个控制器之间共享服务

时间:2014-10-16 22:59:48

标签: angularjs http asynchronous service controller

我是棱角分明的新人,我正面临一些问题...

我有两个共享相同控制器的指令,该控制器是一个服务,在异步调用($ http)上请求json文件。

指令需要相同的数据,并且几乎同时都是init,但我只想进行一次调用并将数据检索到控制器并使用数据更新视图。

MainMenuHeader.js

(function () {
var app = angular.module("mainMenuHeaderModule", ["mainMenuControllerModule"]);

app.directive("mainheader", function () {
    return {
        restrict: "A",
        transclude: true,
        templateUrl: "TMainMenuHeader.html",
        controller: "mainMenuController",
    }
});})();

MainMenuAside.js

(function () {
var app = angular.module("mainMenuAsideModule", ["mainMenuControllerModule"]);

app.directive("mainaside", function () {
    return {
        restrict: "A",
        transclude: true,
        templateUrl: "TMainMenuAside.html",
        controller: "mainMenuController"
    }
});})();

MainMenuController.js

        (function () {
        var app = angular.module("mainMenuControllerModule", ["mainMenuServiceModule"]);

        app.controller("mainMenuController", ["$scope", "MainMenuService",
            function ($scope, MainMenuService)
            {

                $scope.menuList = MainMenuService.GetAsyncData();

                console.log("mainMenuController menuList: " + $scope.menuList);
        }]);
    })
();

MainMenuService.js

    (function () {
    var module = angular.module("mainMenuServiceModule", []);

    module.factory("MainMenuService", ["$q", "$http", function ($q, $http)
    {
        var data;

        var getAsyncData = function()
        {
            console.log(" -> getting data...");
            $http.get("menu.json")
            .success(function(result)
            {
                data = result;

                console.log("async data: " + data);
            });

             return data;
        }


        var getDataObject = function ()
        {
            return [
                        {
                            id:1,
                            title: "Menu 1",
                            submenus: [
                                {
                                    title: "Sub Menu 1",
                                    itens: [
                                        { title: "Option 1" },
                                        { title: "Option 2" },
                                        { title: "Option 3" }
                                    ]
                                }
                            ]
                        },
                        {
                            id:2,
                            title: "Menu 2",
                            submenus: [
                                {
                                    title: "Sub Menu 2",
                                    itens: [
                                        { title: "Option 1" },
                                        { title: "Option 2" },
                                        { title: "Option 3" },
                                        { title: "Option 4" },
                                        { title: "Option 5" }
                                    ]
                                }
                            ]
                        },
                        {
                            id:3,
                            title: "Menu 3",
                            submenus: [
                                {
                                    title: "Sub Menu 3",
                                    itens: [
                                        { title: "Option 1" },
                                        { title: "Option 2" },
                                        { title: "Option 3" }
                                    ]
                                }
                            ]
                        }
                    ];
        }

        return {
            GetDataObject : function()
            {
                return getDataObject();
            },

            GetAsyncData : function()
            {
                return getAsyncData();
            }
        }
    }]);
})();

该服务有两种方法。 一个只返回JS对象进行测试,另一个返回$ http请求无效。

我也尝试从服务中返回延迟并等待控制器的响应,但是没有成功,也许我做错了...有人可以帮助我吗?

我也做了一个plunker,所以你看到问题在行动......

http://plnkr.co/edit/7NIPeAsUYlh96p3hUij7

感谢您的时间...... =)

2 个答案:

答案 0 :(得分:1)

你创造了一个好玩的东西。

问题在于服务的这个功能:

var data;
var getAsyncData = function()
{
    console.log(" -> getting data...");
    $http.get("menu.json")
    .success(function(result)
    {
        data = result;

        console.log("async data: " + data);
    });

     return data;
}

基本上你是将一个未定义的变量返回给控制器,然后发出http请求,当你得到响应时你更新数据来引用结果,但是控制器$ scope.menuList中的仍然指向未定义(你'不要从函数中更新返回的对象。)

修复它你有两个选择:

将视图绑定到您在服务中返回的对象的属性,然后在从http调用获得响应时更新对象属性。 here's the relevant plunker

其他选项是,对于异步调用,您在服务中返回一个promise,一旦解析了promise,控制器就可以使用请求的结果更新范围。 here's the relevant plunker

答案 1 :(得分:0)

我改变了一点我的服务...如果另一个请求在另一个请求正在运行时返回数据引用,并且所有正在调用的人都将在完成后更新:

module.factory("MainMenuService", ["$http", function ($http)
{
    var isRequesting = false;
    var data = {};

    var getAsyncData = function()
    {
        if (isRequesting) return data;

        isRequesting = true;

        console.log(" -> getting async data...");
        $http.get("json/mainMenu.json")
        .success(function (result)
        {
            isRequesting = false;

            angular.forEach(result, function (value, key)
            {
                value.id = key;
                switch(value.submenus.length)
                {
                    case 1: value.columnsSize = 12; break;
                    case 2: value.columnsSize = 6; break;
                    default: value.columnsSize = 4; break;
                } 
            })

            data.menuList = result;

            console.log(" -> data.menuList : " + data.menuList);
        });

        return data;
    }

    return {
        GetAsyncData: function ()
        {
            return getAsyncData();
        }
    }
}]);