Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 角度-从工厂方法检索数据的最佳实践_Javascript_Angularjs_Json_Factory - Fatal编程技术网

Javascript 角度-从工厂方法检索数据的最佳实践

Javascript 角度-从工厂方法检索数据的最佳实践,javascript,angularjs,json,factory,Javascript,Angularjs,Json,Factory,我正在寻找一些关于从本地JSON文件检索数据和处理响应的最佳方法的信息。浏览堆栈溢出后,我有一些混合的想法,因为我看到了多种做同一件事的方法(尽管没有解释为什么一种可能更可取或不可取) 本质上,我有一个Angular应用程序,它利用工厂从JSON文件检索数据;然后,我等待响应在我的控制器中解析,然后在html文件中使用它,如下所示: 选择1 工厂: comparison.factory('Info', ['$http', function($http) { var retrievalFile =

我正在寻找一些关于从本地JSON文件检索数据和处理响应的最佳方法的信息。浏览堆栈溢出后,我有一些混合的想法,因为我看到了多种做同一件事的方法(尽管没有解释为什么一种可能更可取或不可取)

本质上,我有一个Angular应用程序,它利用工厂从JSON文件检索数据;然后,我等待响应在我的控制器中解析,然后在html文件中使用它,如下所示:

选择1 工厂:

comparison.factory('Info', ['$http', function($http) {
var retrievalFile = 'retrievalFile.json';

return {
 retrieveInfo: function() {
  return $http.get(retrievalFile);
 }
}

}]);
comparison.factory('Info', ['$http', function($http) {
var retrievalFile = 'retrievalFile.json';

return {
  retrieveInfo: function() {
    return $http.get(retrievalFile).then(function(response) {
      return response.data;
    });
  }
}

}]);
控制器:

comparison.controller('comparisonController', ['$scope', 'Info', function($scope, Info) {

Info.retrieveInfo().then(function(response) {
  $scope.info = response.data;
});

}]);
comparison.controller('comparisonController', ['$scope', 'Info', function($scope, Info) {

Info.retrieveInfo().then(function(response) {
  $scope.info = response;
});

}]);
我的主要争论点是弄清楚什么时候最好等回应解决,或者它是否重要。我只是想让工厂返回已兑现的承诺,然后等待控制器也检索数据。在我看来,最好是将所有数据检索从控制器中提取出来并放入工厂,但我不确定这是否扩展到等待在工厂内部返回实际数据。考虑到这一点,我对选择选项1还是选项2感到困惑,我非常感谢更有经验/资质的开发人员的反馈

选择2 工厂:

comparison.factory('Info', ['$http', function($http) {
var retrievalFile = 'retrievalFile.json';

return {
 retrieveInfo: function() {
  return $http.get(retrievalFile);
 }
}

}]);
comparison.factory('Info', ['$http', function($http) {
var retrievalFile = 'retrievalFile.json';

return {
  retrieveInfo: function() {
    return $http.get(retrievalFile).then(function(response) {
      return response.data;
    });
  }
}

}]);
控制器:

comparison.controller('comparisonController', ['$scope', 'Info', function($scope, Info) {

Info.retrieveInfo().then(function(response) {
  $scope.info = response.data;
});

}]);
comparison.controller('comparisonController', ['$scope', 'Info', function($scope, Info) {

Info.retrieveInfo().then(function(response) {
  $scope.info = response;
});

}]);

提前感谢您的任何意见/建议

我会选择选项二,因为你的选项基本上是一样的。但是让我们看看什么时候我们添加了一个模型结构,比如一个
Person
假设

comparison.factory('Info',['$http',function($http){
var retrievalFile='retrievalFile.json';
返回{
retrieveInfo:函数(){
返回$http.get(retrievalFile).then(函数(响应){
//我们将返回一个人。。。
var数据=响应数据;
返回新人员(data.name、data.age、data.gender);
});
}
}

}]);这真的只是偏好。我喜欢从API的角度来考虑它。您要公开的API是什么?您是希望控制器接收整个响应,还是希望控制器只包含响应包装的数据?如果您只打算使用
response.data
,那么选项2非常有用,因为除了您感兴趣的数据之外,您不需要处理任何事情

一个很好的例子是我们刚刚在我工作的地方编写的应用程序。我们有两个应用程序:后端API和前端Angular应用程序。我们在前端应用程序中创建了一个API包装器服务。在服务本身中,我们为任何记录了错误代码的API端点放置了一个
.catch
(我们使用Swagger记录并定义了我们的API)。在该
.catch
中,我们处理这些错误代码并返回正确的错误。当我们的控制器/指令使用该服务时,它们会返回一组更严格的数据。如果发生错误,UI通常可以安全地只显示从包装器服务发送的错误消息,而不必担心查看错误代码


同样,对于成功的回答,我们做了您在选项2中所做的大部分工作。在许多情况下,我们将数据细化到实际应用中最不有用的数据。通过这种方式,我们在服务中保留了大量的数据搅动和格式化,而应用程序的其余部分则没有那么多事情要做。例如,如果我们需要基于该数据创建一个对象,我们只需将该对象返回到承诺链,这样控制器就不会到处这样做。

这取决于您的控制器期望什么以及您如何设置应用程序。一般来说,我总是选择第二种选择。这是因为我通常在所有api请求中都有全局错误或成功处理程序,并且我有一个共享的
api服务
。像下面这样

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

app.service('ApiService', ['$http', function($http) {
    var get = function(url, params) {
    $http.get(url, { params: params })
        .then(handleSuccess, handleError);
  };

  // handle your global errors here
  // implementation will vary based upon how you handle error
  var handleError = function(response) {
    return $q.reject(response);
  };

  // handle your success here
  // you can return response.data or response based upon what you want
  var handleSuccess = function(response) {
    return response.data;
  };
}]);

app.service('InfoService', ['ApiService', function(ApiService) {
    var retrieveInfo = function() {
    return ApiService.get(retrievalFile);

    /**
    // or return custom object that your controller is expecting
    return ApiService.get.then(function(data) {
      return new Person(data);
    });
    **//
  };

  // I prefer returning public functions this way
  // as I can just scroll down to the bottom of service 
  // to see all public functions at one place rather than
  // to scroll through the large file
  return { retrieveInfo: retrieveInfo };
}]);

app.controller('InfoController', ['InfoService', function(InfoService) {
  InfoService.retrieveInfo().then(function(info) {
    $scope.info = info;
  });
}])
或者,如果您使用的是路由器,您可以将数据解析到控制器中。ngRouter和uiRouter支持解决以下问题:

$stateProvider.state({
    name: 'info',
  url: '/info',
  controller: 'InfoController',
  template: 'some template',
  resolve: {
    // this injects a variable called info in your controller
    // with a resolved promise that you return here
    info: ['InfoService', function(InfoService) {
        return InfoService.retrieveInfo();
    }]
  }
});

// and your controller will be like
// much cleaner right
app.controller('InfoController', ['info', function(info) {
    $scope.info = info;
}]);

好问题。有两点:

  • 控制器应该以视图为中心而不是以数据为中心,因此 希望从控制器中删除数据逻辑,而不是将其作为焦点 关于业务逻辑
  • 模型(MVC中的M)是应用程序和应用程序的数据表示形式 将包含数据逻辑。在这种情况下,这将是一种服务 或者你正确指出的工厂类。为什么这对我来说很好 例如:

    2.1 AccountsController(可能已注入多个数据模型)

  • 有很多方法可以采用数据模型方法,但我想说,您的服务类应该是数据REST模型,即获取、存储、缓存、验证等。我已经提供了一个基本示例,但建议您研究JavaScript OOP,因为这将帮助您找到正确的方向,了解如何构建数据模型、集合,等等

    下面是一个用于管理数据的服务类示例。请注意,我还没有测试过这段代码,但它应该会给您一个开始

    例如:

        (function () {
            'use strict';
    
            ArticleController.$inject = ['$scope', 'Article'];
            function ArticleController($scope, Article) {
                var vm = this,
                    getArticles = function () {
                        return Article.getArticles()
                            .then(function (result) {
                                if (result) {
                                    return vm.articles = result;
                                }
                            });
                    };
    
    
                vm.getArticles = getArticles;
                vm.articles = {};
                // OR replace vm.articles with $scope if you prefer e.g.
                $scope.articles = {};
    
                $scope.userNgClickToInit = function () {
                    vm.getArticles();
                };
    
                // OR an init on document ready
                // BUT to honest I would put all init logic in service class so all in calling is init in ctrl and model does the rest
                function initArticles() {
                    vm.getArticles();
    
                    // OR chain
                    vm.getArticles()
                        .then(getCategories); // doesn't here, just an example
    
                }
    
                initArticles();
            }
    
            ArticleModel.$inject = ['$scope', '$http', '$q'];
            function ArticleModel($scope, $http, $q) {
                var model = this,
                    URLS = {
                        FETCH: 'data/articles.json'
                    },
                    articles;
    
                function extract(result) {
                    return result.data;
                }
    
                function cacheArticles(result) {
                    articles = extract(result);
                    return articles;
                }
    
                function findArticle(id) {
                    return _.find(articles, function (article) {
                        return article.id === parseInt(id, 10);
                    })
                }
    
                model.getArticles = function () {
                    return (articles) ? $q.when(articles) : $http.get(URLS.FETCH).then(cacheArticles);
                };
    
                model.getArticleById = function (id) {
                    var deferred = $q.defer();
                    if (articles) {
                        deferred.resolve(findArticle(id))
                    } else {
                        model.getBookmarks().then(function () {
                            deferred.resolve(findArticle(id))
                        })
                    }
                    return deferred.promise;
                };
    
                model.createArticle = function (article) {
                    article.id = articles.length;
                    articles.push(article);
                };
    
                model.updateArticle = function (bookmark) {
                    var index = _.findIndex(articles, function (a) {
                        return a.id == article.id
                    });
    
                    articles[index] = article;
                };
    
                model.deleteArticle = function (article) {
                    _.remove(articles, function (a) {
                        return a.id == article.id;
                    });
                };
            }
    
            angular.module('app.article.model', [])
            .controller('ArticleController', ArticleController)
            .service('Article', ArticleModel);
    
        })()
    

    并非总是最好的答案,但Angular的美妙之处在于它不关心如何为您的“模型”处理或维护数据。我看到的最佳实践与选项1类似。我认为从可读性的角度来看,它在服务、数据和控制器之间提供了一个很好的链接。不过这只是我的意见:-DI建议选择1,因为您将在其中的所有方法上使用命令,如successCallback和errorCallback。使用promise(即angular$q服务)会更好。谢谢你(以及其他回答的人),这绝对是值得思考的。我将研究编写一个API服务,以便我的代码易于扩展。