AngularJS : service $diffusion $et montre pas de déclenchement sur la réception de contrôleur
AngularJS noob ici, sur mon chemin de l'Angulaire de l'Illumination 🙂
Voici la situation:
J'ai mis en place un service "AudioPlayer' à l'intérieur de mon module "application" et enregistré comme suit:
app.service('AudioPlayer', function($rootScope) {
//...
this.next = function () {
//loads the next track in the playlist
this.loadTrack(playlist[++playIndex]);
};
this.loadTrack = function(track) {
//... loads the track and plays it
//broadcast 'trackLoaded' event when done
$rootScope.$broadcast('trackLoaded', track);
};
}
et voici le "récepteur" contrôleur (surtout pour les interfaces de la logique de présentation)
app.controller('PlayerCtrl', function PlayerCtrl($scope, AudioPlayer) {
//AudioPlayer broadcasts the event when the track is loaded
$scope.$on('trackLoaded', function(event, track) {
//assign the loaded track as the 'current'
$scope.current = track;
});
$scope.next = function() {
AudioPlayer.next();
};
}
dans mes vues, je montre de la piste en cours info comme:
<div ng-controller="PlayerCtrl">
<button ng-click="next()"></button>
//...
<p id="info">{{current.title}} by {{current.author}}</p>
</div>
la méthode next() est définie dans le PlayerCtrl, et il appelle simplement la même méthode sur l'AudioPlayer service.
Le problème
Cela fonctionne bien quand il y a une interaction manuelle (c'est à dire quand je, cliquez sur le bouton ()) - le flux est la suivante:
- PlayerCtrl intercepte le clic et les feux de sa propre méthode next ()
- qui à son tour déclenche l'AudioPlayer.la méthode next ()
- qui cherche la piste suivante dans la liste de lecture et appelle la loadTrack() la méthode
- loadTrack() $diffuse le " trackLoaded de l'événement (l'envoi de la piste elle-même avec elle)
- la PlayerCtrl écoute l'événement de diffusion et ayants droit de la piste à l'objet en cours
- l'affichage est mis à jour correctement, montrant le courant.titre et actuel.info auteur
Toutefois, lorsque la méthode next() est appelée à partir de la AudioService dans la "toile de fond" (c'est à dire, lorsque la piste est de plus), toutes les étapes de 1 à 5 ne se produisent, mais la vue n'est pas averti de la modification de la PlayerCtrl s 'en cours' objet.
Je peux voir clairement la nouvelle piste de l'objet assigné à la PlayerCtrl, mais c'est comme si la vue n'est pas averti de la modification. Je suis un noob, et je ne suis pas sûr si c'est une aide, mais ce que j'ai essayé est l'ajout d'un $watch expression dans le PlayerCtrl
$scope.$watch('current', function(newVal, oldVal) {
console.log('Current changed');
})
qui est imprimé uniquement pendant le 'manuel' interactions...
Encore une fois, comme je l'ai dit, si j'ajoute une console.journal(en cours) dans l' $sur l'auditeur comme suit:
$scope.$on('trackLoaded', function(event, track) {
$scope.current = track;
console.log($scope.current);
});
ce est imprimé correctement à tout moment.
Ce que je fais mal?
(ps je suis en utilisant AudioJS pour le HTML5 audio player, mais je ne pense pas que ce est le seul à blâmer ici...)
Vous devez vous connecter pour publier un commentaire.
Lorsque vous avez un événement de clic de $champ d'application est mis à jour, sans l'événement, vous aurez besoin d'utiliser $s'appliquent
$scope.current = track; $scope.$apply();
Error: $digest already in progress
dans la console... mh?$apply
fonction qu'il exécute le code à l'intérieur d'untry/catch/finally
: letry/catch
gère l'erreur et lafinally
utilise$digest
pour exécuter votre code indépendamment de l'erreur.$timeout
. Furtivement dans $scope.$$la phase est considérée comme l'interface de la rupture, et peut se briser à tout moment. $timeout garanties (avec les arguments appropriés) pour exécuter une fonction dans un $s'appliquent bloc.Comme il n'est pas sûr à lire dans le recueil internes, le plus simple est d'utiliser
$timeout
:Le rappel est toujours exécutée dans le bon environnement.
EDIT: En fait, la fonction qui doit être enveloppé dans l'appliquer phase est
Sinon, la diffusion se fera à obtenir raté.
~~~~~~
En fait, une alternative pourrait être mieux (au moins à partir d'un point de vue sémantique) et il fonctionnera tout aussi à l'intérieur ou à l'extérieur d'un digest cycle:
$scope.$apply
: vous n'avez pas à savoir si vous êtes dans un condensé de cycle.$timeout
: vous n'êtes pas vraiment envie d'un délai d'attente, et vous obtenez la syntaxe plus simple sans les0
paramètre.Tout essayé, il a travaillé pour moi avec
$rootScope.$applyAsync(function() {});