Я использую 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;
})
};
Как правильно это сделать?
5 ответов
Вы должны использовать $httpProvider.useApplyAsync
и передать {{X1 }}.
Из documentation
:
Настройте службу $ http для объединения обработки нескольких ответов http, полученных примерно в одно и то же время через $ rootScope. $ ApplyAsync. Это может привести к значительному повышению производительности для более крупных приложений, которые одновременно выполняют множество HTTP-запросов (обычно во время начальной загрузки приложения).
Это означает, что если true, то при загрузке запросов они будут планировать отложенное «применение» на следующем тике, давая время для последующих запросов в окне примерно ~ 10 мс для загрузки и совместного использования того же цикла дайджеста.
Короче говоря, вы можете избежать ненужных циклов дайджеста, которые могут иметь огромное значение.
Просто передайте $httpProvider
в свою функцию запуска и измените поставщика следующим образом:
angular.module('MyApp', [])
.run(function($httpProvider){
$httpProvider.useApplyAsync(true);
});
Вы можете использовать сервис $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
каждого раскрывающегося списка для получения данных в каскадном стиле.
Использование обещаний в соответствии с предложением 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
Попробуйте так: ваш контроллер (основной вид):
ViewBag.regionDetailsJson = new JavaScriptSerializer().Serialize(regionDetails );
На ваш взгляд:
var regionDetailsJson = $.parseJSON('@Html.JsonRaw((string)ViewBag.regionDetailsJson )');
И чем в вашем угловом контроллере:
$scope.regionDetailsJson = regionDetailsJson;
В вашем подходе нет ничего плохого. Вы следуете разделению интересов и единственной ответственности.
Если вы получаете дату из модели или модели из представления 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>
Похожие вопросы
Новые вопросы
angularjs
Используйте для вопросов об AngularJS (1.x), JavaScript-фреймворке с открытым исходным кодом. НЕ используйте этот тег для Angular 2 или более поздних версий; вместо этого используйте тег [angular].