Я использую angularjs с asp.net mvc. На моей странице есть 5 раскрывающихся списков, каждый из которых заполнен значениями из разных таблиц базы данных. Чтобы получить данные для всех раскрывающихся списков, я делаю 5 разных запросов $ http.get, что замедляет загрузку моей страницы до сканирования. Я знаю, что это неправильно, но не знаю, как это сделать правильно. Вот мой код angular, который вызывает действие mvc, возвращает значения для раскрывающегося списка и передает результаты в $ scope для отображения раскрывающегося списка:

var CustomSearchController = function ($scope, $http) {    
$http.get('/Account/GetLists')
    .success(function (result) {
        $scope.listDetails = result;
    })        
 };
 $http.get('/Account/GetGenders')
    .success(function (result) {
        $scope.genderDetails = result;
    })        
 };
 $http.get('/Account/GetEthnicities')
    .success(function (result) {
        $scope.ethnicityDetails = result;
    })        
 };
 $http.get('/Account/GetRegions')
    .success(function (result) {
        $scope.regionDetails = result;
    })        
 };
 $http.get('/Account/GetAcademics')
    .success(function (result) {
        $scope.academicDetails = result;
    })        
 };

Как правильно это сделать?

0
goalie35 6 Сен 2016 в 22:38

5 ответов

Лучший ответ

Вы должны использовать $httpProvider.useApplyAsync и передать {{X1 }}.

Из documentation:

Настройте службу $ http для объединения обработки нескольких ответов http, полученных примерно в одно и то же время через $ rootScope. $ ApplyAsync. Это может привести к значительному повышению производительности для более крупных приложений, которые одновременно выполняют множество HTTP-запросов (обычно во время начальной загрузки приложения).

Это означает, что если true, то при загрузке запросов они будут планировать отложенное «применение» на следующем тике, давая время для последующих запросов в окне примерно ~ 10 мс для загрузки и совместного использования того же цикла дайджеста.

Короче говоря, вы можете избежать ненужных циклов дайджеста, которые могут иметь огромное значение.

Просто передайте $httpProvider в свою функцию запуска и измените поставщика следующим образом:

angular.module('MyApp', [])

.run(function($httpProvider){

    $httpProvider.useApplyAsync(true);

});
3
cnorthfield 6 Сен 2016 в 20:00

Вы можете использовать сервис $q для такого сценария, как это:

var CustomSearchController = function ($scope, $q, $log, $http) {
    var listPromise = $http.get('/Account/GetLists');
    var genderPromise = $http.get('/Account/GetGenders');

    var ethnicCitiesPromise = $http.get('/Account/GetEthnicities')

    var regionsPromise = $http.get('/Account/GetRegions')

    var academicPromise = $http.get('/Account/GetAcademics');

    $q.all([genderPromise, ethnicCitiesPromise, regionsPromise, academicPromise])
        .then(function (responses) {
            // Here you have all the resolved datas
            // responses[0]
            // responses[1]
            // responses[2]
            // responses[3]
        }).catch(function (error) {
            $log.error(error);
            throw error;
        })

}

Однако я предпочитаю вызывать функцию ng-change каждого раскрывающегося списка для получения данных в каскадном стиле.

0
Rathma 6 Сен 2016 в 19:45

Использование обещаний в соответствии с предложением HFA - это более угловой подход, но он все равно приведет к 5 вызовам сервера; так что на самом деле это не поможет улучшить производительность загрузки вашей страницы - то есть вы все равно будете ждать выполнения 5 обещаний, прежде чем получите свои данные.

Вы можете попробовать сформулировать эти списки при загрузке страницы, обслуживаемой действием вашей учетной записи MVC, и сохранить их в модели страницы. Затем вы можете получить доступ к этой стороне клиента в блоке сценария, назначив их (глобальной) переменной, к которой вы затем можете получить доступ в Angular.

Я не тестировал это, но у вас был такой подход в прошлом. В качестве руководства вам необходимо выполнить следующие шаги:

В вашем AccountController

public ActionResulst Index() {
    var model = new AccountModel {
     Lists = GetLists(),
     Ethnicities = GetLists()
    }
  return View(model);
}

Затем на вашей странице Razor

@model AccountModel
    <script>
        window.lists= "@(Model.Lists)";
        window.ethnicities = "@(Model.Ethnicities )";
    </script>

Затем в вашем Angular

var CustomSearchController = function ($window) { 

var lists = $window.lists;
var ethnicities  = $window.ethnicities;
}

Возможно, вам потребуется преобразовать результаты в JSON с помощью JSON.Parse

0
Kildareflare 6 Сен 2016 в 20:04

Попробуйте так: ваш контроллер (основной вид):

ViewBag.regionDetailsJson = new JavaScriptSerializer().Serialize(regionDetails );

На ваш взгляд:

var regionDetailsJson = $.parseJSON('@Html.JsonRaw((string)ViewBag.regionDetailsJson )');

И чем в вашем угловом контроллере:

$scope.regionDetailsJson = regionDetailsJson;
0
tata.leona 6 Сен 2016 в 20:02

В вашем подходе нет ничего плохого. Вы следуете разделению интересов и единственной ответственности.

Если вы получаете дату из модели или модели из представления ASP.Net MVC, вы не сможете легко провести модульное тестирование Angular Services.

Другой подход - использовать разрешить < / em> . Обычно он загружает данные перед выполнением маршрута. FYI : это не улучшит общее время загрузки, хотя вы можете отобразить значок загрузки страницы.

Демо для Angular 1.5 Route Resolve в Plunker

(function () {

    angular
      .module("app", ['ngRoute'])
      .config(function($routeProvider){
        $routeProvider
          .when("/home", {
              template: `<main 
                promise-followers="$resolve.promiseFollowers"></main>`,
              resolve: {promiseFollowers: function ($http) {
                    return $http.get("https://api.github.com/users/octocat/followers")
                      .then(function(result) { 
                        return result.data;
                      }, function(result) { 
                        console.log(result);
                      });
                }
              },
          })
          .otherwise({ redirectTo: "/home" } );
      })
      .component("main", {
        template: `<h3>Demo Angular 1.5 Resolver</h3>
        
        <p>Promise Data from Resolve : 
          <select ng-model="$ctrl.selected" 
            ng-options="option.id as option.login for option in $ctrl.promiseFollowers"></select>
        </p>        
        
        <h4>Regular Selector Selected: {{$ctrl.selected}}</h4>`, 
        bindings: {
          promiseFollowers: '='
        },
        
        controller: function(){
          
        }
      });
      
})();
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script src="https://code.angularjs.org/1.5.7/angular.js"></script>
    <script src="https://code.angularjs.org/1.5.7/angular-route.js"></script>
    <script src="app.js"></script>
  </head>

  <body>
    <ng-view></ng-view>
  </body>

</html>
0
Win 6 Сен 2016 в 20:20