AngularJS : 서비스 $broadcast 및 $watch가 수신 컨트롤러에서 트리거되지 않음
Angular JS nook 여기, Angular Envelopment로 가는 나의 길 :)
상황은 이렇습니다.
제 모듈 '앱' 안에 '오디오 플레이어' 서비스를 구현하여 다음과 같이 등록하였습니다.
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);
};
}
여기 '수신기' 컨트롤러(주로 UI/프레젠테이션 로직용)가 있습니다.
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();
};
}
현재 트랙 정보는 다음과 같이 표시합니다.
<div ng-controller="PlayerCtrl">
<button ng-click="next()"></button>
// ...
<p id="info">{{current.title}} by {{current.author}}</p>
</div>
다음() 메서드는 PlayerCtrl에 정의되어 있으며 오디오 플레이어 서비스에서 동일한 메서드를 호출합니다.
문제가
수동 상호 작용이 있을 때(즉, 다음() 버튼을 클릭할 때), 흐름은 다음과 같습니다.
- 플레이어 Ctrl이 클릭을 가로채 자신의 다음() 방법을 발사합니다.
- 그러면 AudioPlayer.next() 메서드가 실행됩니다.
- 재생 목록에서 다음 트랙을 찾고 loadTrack() 메서드를 호출합니다.
- loadTrack() $broadcasting 'trackLoaded' 이벤트(트랙 자체를 함께 전송)
- 플레이어 Ctrl은 브로드캐스트 이벤트를 듣고 트랙을 현재 개체에 할당합니다.
- 보기가 올바르게 업데이트되고 current. title 및 current가 표시됩니다.저자정보
그러나 '백그라운드'(즉, 트랙이 끝나면)의 오디오 서비스 내에서 다음() 메서드가 호출되면 1부터 5까지의 모든 단계가 수행되지만 보기는 플레이어 Ctrl의 '현재' 개체의 변경 사항을 알리지 않습니다.
플레이어 Ctrl에서 새 트랙 객체가 할당되는 것을 명확하게 볼 수 있지만, 보기에 변경 사항이 통지되지 않는 것과 같습니다.저는 초보자인데 도움이 될지는 모르겠지만 PlayerCtrl에서 $watch 표현을 추가하려고 했습니다.
$scope.$watch('current', function(newVal, oldVal) {
console.log('Current changed');
})
'수동' 상호작용을 할 때만 출력됩니다
다시 말하지만, 이미 말했듯이 $on listener에 console.log(current)를 이렇게 추가하면 다음과 같습니다.
$scope.$on('trackLoaded', function(event, track) {
$scope.current = track;
console.log($scope.current);
});
항상 올바르게 인쇄됩니다.
내가 뭘 잘못하고 있는 거지?
(ps HTML5 오디오 플레이어에 AudioJS를 사용하고 있지만 여기서 탓할 일은 아닌 것 같습니다...)
클릭 이벤트가 있을 때 $scope이 업데이트되고 이벤트가 없으면 $apply를 사용해야 합니다.
$scope.$apply(function () {
$scope.current = track;
});
소화기 내부를 들여다보는 것은 안전하지 않기 때문에 가장 쉬운 방법은$timeout:
$timeout(function () {
$scope.current = track;
}, 0);
콜백은 항상 좋은 환경에서 실행됩니다.
편집: 실제로 적용 단계에서 랩핑해야 하는 기능은
this.loadTrack = function(track) {
// ... loads the track and plays it
// broadcast 'trackLoaded' event when done
$timeout(function() { $rootScope.$broadcast('trackLoaded', track); });
};
그렇지 않으면 방송이 빗나갈 것입니다.
~~~~~~
실제로, (적어도 의미론적 관점에서) 대안이 더 나을 수 있으며, 그것은 다이제스트 사이클 내부 또는 외부에서 동일하게 작동할 것입니다.
$scope.$evalAsync(function (scope) {
scope.current = track;
});
- 에서의 이점
$scope.$apply를 알 당신이 소화 주기에 있는지 알 필요는 없습니다. - 에서의 이점
$timeout, 를 더 수 .0매개 변수.
// apply changes
$scope.current = track;
try {
if (!$scope.$$phase) {
$scope.$apply($scope.current);
}
} catch (err) {
console.log(err);
}
걸 요, 와 잘 $rootScope.$applyAsync(function() {});
언급URL : https://stackoverflow.com/questions/12928840/angularjs-service-broadcast-and-watch-not-triggering-on-receiving-controller
'programing' 카테고리의 다른 글
| XMLHttpRequest 개체를 재사용하시겠습니까? 아니면 새 개체를 만드시겠습니까? (0) | 2023.09.20 |
|---|---|
| WMI가 없는 PowerShell을 사용하여 총 물리적 메모리 크기를 얻으려면 어떻게 해야 합니까? (0) | 2023.09.20 |
| 오라클에서 varchar2 필드를 더 짧게 만드는 방법은? (0) | 2023.09.20 |
| 사용자 정의 wp_query에서 워드프레스 페이지(next_posts_link)가 표시되지 않음 (0) | 2023.09.20 |
| 이름별 쿼리 테이블 개체 참조 (0) | 2023.09.20 |