AngularJS : 필터를 비동기적으로 초기화합니다.
비동기 데이터로 필터를 초기화하는 데 문제가 있습니다.
필터는 매우 간단해서 이름으로 경로를 변환해야 하지만 그러기 위해서는 서버에서 가져와야 하는 대응 배열이 필요합니다.
함수를 반환하기 전에 필터 정의의 작업을 수행할 수는 있지만 비동기적인 측면은 이를 방지합니다.
angular.module('angularApp').
filter('pathToName', function(Service){
// Do some things here
return function(input){
return input+'!'
}
}
약속을 사용하는 것이 실행 가능할 수도 있지만, 저는 필터의 각도 부하가 어떻게 되는지에 대해 명확한 이해를 하지 못합니다.이 게시물은 서비스로 그러한 마법을 달성하는 방법을 설명하고 있습니다만, 필터에 대해서도 같은 방법이 가능합니까?
그리고 그 길들을 번역하는 방법에 대해 더 좋은 생각을 가진 사람이 있다면, 저는 귀를 쫑긋 세우고 있습니다.
편집:
약속을 지키려고 노력했지만 뭔가가 잘못되었고 무엇이 있는지 알 수가 없습니다.
angular.module('angularApp').filter('pathToName', function($q, Service){
var deferred = $q.defer();
var promise = deferred.promise;
Service.getCorresp().then(function(success){
deferred.resolve(success.data);
}, function(error){
deferred.reject();
});
return function(input){
return promise.then(
function(corresp){
if(corresp.hasOwnProperty(input))
return corresp[input];
else
return input;
}
)
};
});
저는 약속을 잘 모르는데, 사용하는 방법이 맞나요?
다음은 예입니다.
app.filter("testf", function($timeout) {
var data = null, // DATA RECEIVED ASYNCHRONOUSLY AND CACHED HERE
serviceInvoked = false;
function realFilter(value) { // REAL FILTER LOGIC
return ...;
}
return function(value) { // FILTER WRAPPER TO COPE WITH ASYNCHRONICITY
if( data === null ) {
if( !serviceInvoked ) {
serviceInvoked = true;
// CALL THE SERVICE THAT FETCHES THE DATA HERE
callService.then(function(result) {
data = result;
});
}
return "-"; // PLACEHOLDER WHILE LOADING, COULD BE EMPTY
}
else return realFilter(value);
}
});
이 바이올린은 서비스 대신 타임아웃을 사용하는 시연입니다.
편집: 스기메노의 지적에 따르면, 서비스를 한 번 이상 호출하지 않은 것에 대해 각별히 주의해야 합니다.참조.serviceInvoked
위의 코드와 바이올린의 변화.값을 변경하고 다이제스트 사이클을 트리거하려면 각 1.2.1을 사용하는 포크 피들과 버튼을 참조하십시오.
편집 2: Miha Er žen의 코멘트에 따르면, 이 솔루션은 Angular 1.3에서는 로그너가 작동하지 않습니다.그러나 솔루션은 거의 사소합니다.$stateful
여기 "Stateful filters" 아래에 문서화된 필터 플래그와 필요한 포크 피들.
필터를 각 다이제스트 사이클(digest cycle)이라고 부르기 때문에 이 솔루션은 성능을 저하시킨다는 점에 유의하십시오.성능 저하는 특정한 경우에 따라 무시할 수도 있고 그렇지 않을 수도 있습니다.
왜 원래의 코드가 작동하지 않는지 이해하는 것부터 시작하겠습니다.좀 더 명확하게 하기 위해 원래 질문을 조금 단순화했습니다.
angular.module('angularApp').filter('pathToName', function(Service) {
return function(input) {
return Service.getCorresp().then(function(response) {
return response;
});
});
}
기본적으로 필터는 약속을 반환하는 비동기 함수를 호출한 다음 값을 반환합니다.각도로 표시된 필터는 문자열 또는 숫자와 같이 쉽게 인쇄할 수 있는 값을 반환합니다.그런데 이 경우에는 반환하는 것처럼 보여도.response
의getCorresp
, 우리는 실제로 새로운 약속을 반환하고 있습니다 - 모든 것의 반환 가치.then()
아니면catch()
기능은 약속입니다.
Angular가 캐스팅을 통해 약속 개체를 문자열로 변환하려고 하면 아무것도 인식되지 않고 빈 문자열이 표시됩니다.
따라서 임시 문자열 값을 반환하고 다음과 같이 비동기적으로 변경해야 합니다.
HTML:
<div ng-app="app" ng-controller="TestCtrl">
<div>{{'WelcomeTo' | translate}}</div>
<div>{{'GoodBye' | translate}}</div>
</div>
자바스크립트:
app.filter("translate", function($timeout, translationService) {
var isWaiting = false;
var translations = null;
function myFilter(input) {
var translationValue = "Loading...";
if(translations)
{
translationValue = translations[input];
} else {
if(isWaiting === false) {
isWaiting = true;
translationService.getTranslation(input).then(function(translationData) {
console.log("GetTranslation done");
translations = translationData;
isWaiting = false;
});
}
}
return translationValue;
};
return myFilter;
});
Angular가 필터를 실행하려고 할 때마다 번역이 이미 가져온 것인지 확인하고 그렇지 않은 경우 "로딩.."을 반환합니다." 값어치를 보다우리는 또한 사용합니다.isWaiting
서비스를 두 번 이상 호출하지 않도록 하는 값입니다.
위의 예는 Angular 1.2에 대해서는 잘 작동하지만 Angular 1.3의 변화 중 필터의 거동을 변화시키는 성능 개선이 있습니다.이전에는 필터 함수를 매 다이제스트 사이클이라고 불렀습니다.를 호출합니다.는 필터를 호출하지 않습니다.나 1.3합니다. 마지막 샘플에서는 다시는 필터를 호출하지 않습니다.'WelcomeTo'
변하지 않을 겁니다
다행히도 해결 방법은 매우 간단합니다. 필터에 다음 사항을 추가하면 됩니다.
myFilter.$stateful = true;
마지막으로 이 문제를 처리하는 동안 또 다른 문제가 생겼습니다. 변경할 수 있는 비동기 값을 얻기 위해 필터를 사용해야 했습니다. 특히 단일 언어에 대한 번역을 가져와야 했지만 사용자가 언어를 변경한 후에는 새 언어 집합을 가져와야 했습니다.그렇게 하는 것은, 비록 개념은 같지만, 조금 더 까다롭다는 것을 증명했습니다.이 코드는 다음과 같습니다.
var app = angular.module("app",[]);
debugger;
app.controller("TestCtrl", function($scope, translationService) {
$scope.changeLanguage = function() {
translationService.currentLanguage = "ru";
}
});
app.service("translationService", function($timeout) {
var self = this;
var translations = {"en": {"WelcomeTo": "Welcome!!", "GoodBye": "BYE"},
"ru": {"WelcomeTo": "POZHALUSTA!!", "GoodBye": "DOSVIDANYA"} };
this.currentLanguage = "en";
this.getTranslation = function(placeholder) {
return $timeout(function() {
return translations[self.currentLanguage][placeholder];
}, 2000);
}
})
app.filter("translate", function($timeout, translationService) {
// Sample object: {"en": {"WelcomeTo": {translation: "Welcome!!", processing: false } } }
var translated = {};
var isWaiting = false;
myFilter.$stateful = true;
function myFilter(input) {
if(!translated[translationService.currentLanguage]) {
translated[translationService.currentLanguage] = {}
}
var currentLanguageData = translated[translationService.currentLanguage];
if(!currentLanguageData[input]) {
currentLanguageData[input] = { translation: "", processing: false };
}
var translationData = currentLanguageData[input];
if(!translationData.translation && translationData.processing === false)
{
translationData.processing = true;
translationService.getTranslation(input).then(function(translation) {
console.log("GetTranslation done");
translationData.translation = translation;
translationData.processing = false;
});
}
var translation = translationData.translation;
console.log("Translation for language: '" + translationService.currentLanguage + "'. translation = " + translation);
return translation;
};
return myFilter;
});
언급URL : https://stackoverflow.com/questions/19046641/angularjs-asynchronously-initialize-filter
'programing' 카테고리의 다른 글
gcc warning: 스칼라 이니셜라이저 주위에 대괄호가 있음 (0) | 2023.10.01 |
---|---|
'on clause'에 알 수 없는 열(열 별칭이 오류를 일으키는 것 같습니다.) (0) | 2023.10.01 |
람다를 사용하여 Excel에서 모든 순열 생성 (0) | 2023.10.01 |
오라클 11g & jdk 1.6과 함께 사용할 jdbc jar 및 db 자체에 연결하는 방법 (0) | 2023.10.01 |
각도가 올바르게 로드되었는지 확인하는 방법 (0) | 2023.10.01 |