0

这个问题大约一半是实际的,一半是概念的。我已经查看了对类似问题的回答,但我对 AngularJS 还是很陌生,我只是不确定最好的方法(我已经看到了一些不同的意见)来做到这一点(对我来说,无论如何),或者真的,我要写的实际代码,这就是为什么我用我自己的应用程序的细节来问这个问题。

我知道这里有很多标题相似的问题,但我敦促您继续阅读。

简而言之,我有一堆控制器,因为我有很多模型要放在一个页面中。当前端向我的任何后端控制器发送请求(即用户操作)时,前端将获得如下所示的响应:

{"success":false,"errors":[{"text":"这是从 PHP 控制器发送的错误。","type":"critical"}]}

但是,我想使用 AngularJS 为我的错误日志创建模型和视图(它只需要存在于客户端)。所以换句话说,应用程序中的每个其他控制器都需要访问错误日志控制器才能将事件添加到错误日志中。

我想我知道一些选项,比如创建共享服务/工厂和广播到 rootscope。我还想知道让每个其他控制器成为处理错误、警报等的控制器的孩子是否有意义,尽管本能地,这对我来说是错误的。

最好的方法是什么(请记住,处理错误的同一个控制器也可能处理警报和其他全局类型的内务处理),并且有人愿意帮助我基于这个模型的实际代码我嘲笑这种行为会是什么样子?

这是在 JSFiddle:http: //jsfiddle.net/Ww8sS/2/

这是代码。这里可能有很多事情不是做某事的最佳方式,但现在,我只关心我所描述的问题。

JS:

var userInterfaceApp = angular.module('user-interface', ['userInterfaceFilters']);

userInterfaceApp.controller('AnotherController', ['$scope', '$http', function($scope, $http) {

    $scope.doSomething = function() {
        $http({method: "JSONP", url: "http://uatu.net/test.php?action=do_something&callback=JSON_CALLBACK"}).
        success(function(data) {
            if(!data.success) {
                alert("How do I get the errors in data.errors to my error log?");
            }
        })
        .error(function(data, status, headers, config) {
            alert("Failure");
        // called asynchronously if an error occurs
        // or server returns response with an error status.
        });
    }
}]);

userInterfaceApp.controller('ConsoleEventController', ['$scope', function($scope) {
    $scope.errorLog = [];
    $scope.errorSortOrder = "-timestamp";

    $scope.addToErrorLog = function(errorArray) {
        for (var i = 0; i < errorArray.length; i++) {
            $scope.errorLog.push({"text" : errorArray[i].text, "type" : errorArray[i].type, "timestamp" : new Date()});
        }
    }

    //Not a real method--just here for demonstration
    $scope.createErrorMessage = function() {
        $scope.addToErrorLog([{"text" : "This is a sample error.", "type" : "critical"}]);
    }
}]);

var userInterfaceFilters = angular.module("userInterfaceFilters", []);

userInterfaceFilters.filter("logTimestamp", function() {
    return function(logDate) {
        var hours = logDate.getHours();
        var minutes = (logDate.getMinutes() < 10) ? "0" + logDate.getMinutes() : logDate.getMinutes();
        var seconds = (logDate.getSeconds() < 10) ? "0" + logDate.getSeconds() : logDate.getSeconds();
        return hours + ':' + minutes + ":" + seconds;
    };
});

我不得不使用 JSONP 使它在 JSFiddle 上工作。我不会在我的实际程序中这样做,因为它都在我的服务器上。

HTML:

<div ng-app="user-interface">
    <div ng-controller="AnotherController">
    <input type="button" value="Do Something" ng-click="doSomething()">    
    </div>

    <div ng-controller="ConsoleEventController">
        <p><input type="button" value="Create Error Message" ng-click="createErrorMessage()"></p>
        <h1>Error Log</h1>
        <ul id="error-log">
            <li ng-repeat="error in errorLog | orderBy:errorSortOrder" class="error-{{error.type}}">&lt;{{error.timestamp|logTimestamp}}&gt; {{error.text}}</li>
        </ul>
    </div>
</div>
4

2 回答 2

2

听起来您已经知道最好的方法是沿着工厂/服务路线走。不过没有必要broadcast——他们只是创建一个实例,您可以在必要时注入该实例。

这是一个快速示例,说明如何进行操作:http: //jsfiddle.net/Ww8sS/3/

于 2013-08-01T09:52:58.020 回答
1

对我来说,使用消息传递范例(广播)而不是使用创建变量的工厂更有意义,该变量在绑定到控制器的范围后,因为它确实使控制器和服务/工厂耦合,因此您永远无法更改变量服务/工厂,因为您的控制器将失去与服务/工厂变量的链接。

例如,如果您想在服务/工厂中创建一个清除日志数组的新方法,以便创建新数组而不是清空当前数组,那么该更改将不会反映在该控制器的作用域中,因为作用域的变量点到旧日志的数组;看看这个例子:http: //jsfiddle.net/Ww8sS/6/

var userInterfaceApp = angular.module('user-interface', ['userInterfaceFilters']);

userInterfaceApp.factory('errorLogs', function () {
    return {
        logs: [],
        addToErrorLog: function (errorArray) {
            for (var i = 0; i < errorArray.length; i++) {
                this.logs.push({"text": errorArray[i].text, "type": errorArray[i].type, "timestamp": new Date()});
            }
        },
        clearLogs: function () {
            this.logs = [];
        }
    }
});

userInterfaceApp.controller('AnotherController',
    ['$scope', '$http', 'errorLogs', function ($scope, $http, errorLogs) {

        $scope.doSomething = function () {
            $http({method: "JSONP", url: "http://uatu.net/test.php?action=do_something&callback=JSON_CALLBACK"}).
                success(function (data) {
                    if (!data.success) {
                        errorLogs.addToErrorLog(data.errors);
                    }
                })
                .error(function (data, status, headers, config) {
                    alert("Failure");
                    // called asynchronously if an error occurs
                    // or server returns response with an error status.
                });
        }
    }]);

userInterfaceApp.controller('ConsoleEventController',
    ['$scope', 'errorLogs', function ($scope, errorLogs) {
        $scope.errorLog = errorLogs.logs;
        $scope.errorSortOrder = "-timestamp";

        //Not a real method--just here for demonstration
        $scope.createErrorMessage = function () {
            errorLogs.addToErrorLog([
                {"text": "This is a sample error.", "type": "critical"}
            ]);
        }

        $scope.clearLogs = function () {
            errorLogs.clearLogs();
        };

    }]);

var userInterfaceFilters = angular.module("userInterfaceFilters", []);

userInterfaceFilters.filter("logTimestamp", function () {
    return function (logDate) {
        var hours = logDate.getHours();
        var minutes = (logDate.getMinutes() < 10) ? "0" + logDate.getMinutes() : logDate.getMinutes();
        var seconds = (logDate.getSeconds() < 10) ? "0" + logDate.getSeconds() : logDate.getSeconds();
        return hours + ':' + minutes + ":" + seconds;
    };
});

如果使用消息传递范式,它将控制器与服务解耦,而且服务是独立的,任何控制器都可以监听其事件;http://jsfiddle.net/Ww8sS/5/

    var userInterfaceApp = angular.module('user-interface', ['userInterfaceServices', 'userInterfaceFilters']);

    userInterfaceApp.controller('AnotherController', ['$scope', '$http', 'logger', function($scope, $http, logger) {

        $scope.doSomething = function() {
            $http({method: "JSONP", url: "http://uatu.net/test.php?action=do_something&callback=JSON_CALLBACK"}).
            success(function(data) {
                if(!data.success) {
                    logger.addToErrorLog(data.errors);
                    //alert("How do I get the errors in data.errors to my error log?");
                }
            })
            .error(function(data, status, headers, config) {
                alert("Failure");
            // called asynchronously if an error occurs
            // or server returns response with an error status.
            });

        }

         $scope.clearLog = function() {
          logger.clearLog();      
        }
    }]);

    userInterfaceApp.controller('ConsoleEventController', ['$scope', function($scope) {
        $scope.errorSortOrder = "-timestamp";
        $scope.errorLog;

        $scope.$on('logger.newErrors', function (evt, errArray) {  
             $scope.errorLog = errArray;
            });

        $scope.$on('logger.clearLog', function (evt) {  
             $scope.errorLog = [];
            });


        //Not a real method--just here for demonstration
        $scope.createErrorMessage = function() {
           // $scope.addToErrorLog([{"text" : "This is a sample error.", "type" : "critical"}]);
        }
    }]);

var userInterfaceFilters = angular.module("userInterfaceFilters", []);

userInterfaceFilters.filter("logTimestamp", function() {
    return function(logDate) {
        var hours = logDate.getHours();
        var minutes = (logDate.getMinutes() < 10) ? "0" + logDate.getMinutes() : logDate.getMinutes();
        var seconds = (logDate.getSeconds() < 10) ? "0" + logDate.getSeconds() : logDate.getSeconds();
        return hours + ':' + minutes + ":" + seconds;
    };
});


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

userInterfaceServices.service('logger', ['$rootScope', function ($rootScope) {

        var errorLog = [];

        this.addToErrorLog = function(errorArray) {
            for (var i = 0; i < errorArray.length; i++) {
                errorLog.push({"text" : errorArray[i].text, "type" : errorArray[i].type, "timestamp" : new Date()});
            }

            $rootScope.$broadcast('logger.newErrors', errorLog);
        };

    this.clearLog = function () {
      errorLog = [];
        $rootScope.$broadcast('logger.clearLog', '');
    };
}]);

无论如何,这两种解决方案都有一些优点和缺点。

于 2013-08-01T11:09:43.457 回答