angularjs - example - promesas en angular 6
JS angular: cómo vincularse a las promesas (3)
ADVERTENCIA : esta respuesta fue precisa cuando fue escrita, pero a partir de 1.2 el motor de plantilla angular no maneja las promesas de manera transparente. - @Malvolio
Sí, el motor de plantillas (y expresiones) maneja las promesas de manera transparente, pero asigno la promesa a una propiedad de alcance en el controlador y no llamo cada vez a una función que devuelve una nueva promesa (creo que es su problema, la promesa resuelta se pierde porque un nuevo la promesa se devuelve cada vez).
JSFiddle: http://jsfiddle.net/YQwaf/36/
HTML:
<div ng:controller="addressValidationController">
Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in regions"/>
Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>
JS:
function addressValidationController($scope, $q, $timeout) {
var regions = {
US: [{
code: ''WI'',
name: ''Wisconsin''},
{
code: ''MN'',
name: ''Minnesota''}],
CA: [{
code: ''ON'',
name: ''Ontario''}]
};
function getRegions(countryCode) {
console.log(''getRegions: '' + countryCode);
var deferred = $q.defer();
$timeout(function() {
var countryRegions = regions[countryCode];
if (countryRegions === undefined) {
console.log(''resolve empty'');
deferred.resolve([]);
} else {
console.log(''resolve'');
deferred.resolve(countryRegions);
}
}, 1000);
return deferred.promise;
};
$scope.regions = [];
// Manage country changes:
$scope.$watch(''countryCode'', function(countryCode) {
if (angular.isDefined(countryCode)) {
$scope.regions = getRegions(countryCode);
}
else {
$scope.regions = [];
}
});
}
Estoy tratando de atar una promesa a una vista. No sé si puedes hacer eso directamente, pero eso es lo que intento hacer. ¿Alguna idea de lo que estoy haciendo mal?
Nota: la fuente es un poco artificial con el tiempo de espera y utiliza datos estáticos, pero eso hace que el código sea más fácil de diagnosticar.
EDITAR: JSFiddle Page: http://jsfiddle.net/YQwaf/27/
EDITAR: SOLUCIÓN: Resultó que puedes vincular directamente las promesas. Tuve dos problemas con mi código original:
- Utilizar setTimeout () en lugar del tiempo de espera de angular $ fue un problema. Angular no sabe que necesita actualizar la UI cuando se dispara el tiempo de espera (Puede resolver esto con $ scope. $ Apply dentro de setTimeout, o simplemente puede usar $ timeout)
- La vinculación a una función que devolvió una promesa fue un problema. Si se llama por segunda vez, hace otra promesa. Mejor es establecer una variable de alcance para la promesa y solo crear una nueva promesa según sea necesario. (En mi caso, esto llamaba $ scope. $ Watch en el código de país)
HTML:
<div ng:controller="addressValidationController">
Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in getRegions()"/>
Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>
JS:
function addressValidationController($scope, $q) {
var regions = {
US: [{code: ''WI'',name: ''Wisconsin''}, {code: ''MN'',name: ''Minnesota''}],
CA: [{code: ''ON'',name: ''Ontario''}]
};
$scope.getRegions = function () {
var deferred = $q.defer();
setTimeout(function () {
var countryRegions = regions[$scope.countryCode];
console.log(countryRegions);
if(countryRegions === undefined) {
deferred.resolve([]);
} else {
deferred.resolve(countryRegions);
}
}, 1000);
return deferred.promise;
};
}
A partir de Angular 1.2, ya no puedes usar las promesas en las plantillas directamente .
En su lugar, debe poner el resultado en $scope
adentro, como lo haría normalmente, sin magia.
Como una solución temporal para obtener el comportamiento anterior, puede llamar
$parseProvider.unwrapPromises(true)
pero esta característica se eliminará más adelante, así que no dependas de ella.
A partir de Angular 1.3 - $parseProvider.unwrapPromises(true)
ya no funcionará .
En cambio, deberías desenvolver las promesas directamente:
myApiMethod().then(function(value){
$scope.item = value;
});
Tenga en cuenta que la promesa de desenvolver aún funcionará con ngResource como de costumbre.