讓我們從理解原始代碼不起作用的開始。我已經簡化了原來的問題有點更清楚:
angular.module('angularApp').filter('pathToName', function(Service) {
return function(input) {
return Service.getCorresp().then(function(response) {
return response;
});
});
}
一般而言,過濾器調用返回的承諾異步函數,然後返回它的值。角度過濾器期望您返回可以輕鬆打印的值,例如字符串或數字。然而,在這種情況下,即使它看起來像我們返回的getCorresp
的response
,我們實際上返回新承諾 - 任何then()
或catch()
函數的返回值是一個承諾。
Angular正試圖通過強制轉換承諾對象爲字符串,沒有得到任何合理的回報,並顯示一個空字符串。
因此,我們需要做的是,將臨時字符串值和asynchroniously改變它,就像這樣:
JSFiddle
HTML:
<div ng-app="app" ng-controller="TestCtrl">
<div>{{'WelcomeTo' | translate}}</div>
<div>{{'GoodBye' | translate}}</div>
</div>
Javascript:
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嘗試執行過濾器,它會檢查翻譯是否已被提取,如果它們不是,它會返回「Loading ...」值。我們還使用isWaiting
值來防止多次呼叫該服務。
上述示例適用於Angular 1.2,但是,在Angular 1.3中的更改中,性能改進會改變過濾器的行爲。以前,每個摘要循環都會調用過濾器函數。但是,從1.3開始,如果值被更改,它只會調用過濾器,在我們的最後一個樣本中,它不會再次調用過濾器 - 'WelcomeTo'
永遠不會改變。
幸運的是,修復程序非常簡單,你只需要添加到過濾器中的以下內容:
JSFiddle
myFilter.$stateful = true;
最後,在處理這個問題上,我有另一個問題 - 我需要使用過濾器來獲取異步值,可以更改 - 具體而言,我需要爲單一語言提取翻譯,但一旦用戶改變了語言,我需要獲取一個新的語言集。這樣做,證明有點棘手,儘管概念是相同的。這是代碼:
JSFiddle
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;
});
對於現在的過濾器去抓取的對應關係數據,並將其放入過濾器內的變種。這場戰爭然後被用來翻譯事情。 事情是不完美的,如果服務器響應花費很多時間,過濾器將不會有對應的數據,在這種情況下,它不會翻譯。 – Davounet
您可以返回該功能的承諾:http://docs.angularjs.org/api/ng.$q –