After having same issues as many people on StackOverflow i didn't manage to understand what is an "Outside angular zone" Service ?
I've checks all existing questions around this subject, and it's exactly why i needer to ask this one :
- https://github.com/angular/angular/issues/5150
- Angular2: view is not updated from inside a subscription
- https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
- http://blog.assaf.co/angular-2-change-detection-zones-and-an-example/
Code Example in any component with default ChangeDetectionStrategy : (considering this.value referenced in view)
this.myService.method().subscribe(e => {
this.value = e;
});
Is the given service is not "Outside angular zone", the view is refreshed, on the other hand, if it's "Outside angular zone", the view is not refreshed, unless we call ChangeDetectorRef.detectChanges().
So the question is : what the condition to know if a service is Inside or Outside "Angular Zone" ?
The code you want is NgZone.isInAngularZone()
. This will tell you whether or not it's executing there.
Source: hours of banging my head against the wall reading Angular docs before writing this.
Additionally, you can inject NgZone
into your service and try using this.ngZone.run(() => yourSubscriberCallback())
which should help, though I'm having very mixed results attempting this.
EDIT: Okay, I managed to get my stuff working, let's see if it helps you.
In my case I was using a third party library that included a listener for changes. I was using an RXJS BehaviorSubject
to propagate these changes to various components via a service, but the changes weren't being picked up.
It turns out that this was because the method I used in the listener was executing outside of the AngularZone.
At first I was doing this:
export class Service {
public BehaviorSubject<Thing> thingSubject = new BehaviorSubject<Thing>(new Thing());
constructor(private ngZone:NgZone) {
thirdPartyLibrary.listen(ngZone.run(() => myCallback.bind(_this)));
}
...
}
And myCallback
was doing:
myCallback(thing) {
this.thingSubject.next(thing);
}
Turns out this didn't seem to execute within the Angular Zone correctly. I changed my code to this though and it worked:
export class Service {
public BehaviorSubject<Thing> thingSubject = new BehaviorSubject<Thing>(new Thing());
constructor(private ngZone:NgZone) {
thirdPartyLibrary.listen(myCallback.bind(_this));
}
myCallback(thing) {
this.ngZone.run(() => this.thingSubject.next(thing));
}
}
After doing that all my subscribers received the message within the Angular Zone and triggered the expected updates.
As far as I know, it is not possible to check whether something runs "Inside" or "Outside" angular zone. If you use zone.runOutsideAngular
it runs outside your zone. Second comes to my mind: Why would you want to know?
It looks like I found my responses by myself, but i Hope it will be an assistance for other people :
an "Outside Angular Zone" service is a class that was not instantiate inside Angular Context. Many libraries using static accessors are susceptible to be in this case, here's an example :
http://techqa.info/programming/question/34592857/view-is-not-updated-on-change-in-angular2
My luck is that it was the same library used. As described in this external resource, manage to instantiate the external library object would resolve view refresh issue and let this service became an "Inside Angular zone" one.
来源:https://stackoverflow.com/questions/44391696/angular-2-what-make-a-service-to-be-outside-angular-zone