Purpose of zone.js/dist/zone-patch-rxjs
Asked Answered
D

1

14

Probably I am too late with the question but anyway.

Could someone explain me in what cases I need to import zone's patch - zone.js/dist/zone-patch-rxjs. As far as I know the patch was added in this PR (successor of this one).

I use zone and RxJs in my Angular project and despite seeing make rxjs run in correct zone in PR's description I do not fully understand when it can help me or what problems it should resolve for me.

I would appreciate some code examples like before/after.

Thanks in advance.

Dees answered 10/6, 2018 at 14:36 Comment(0)
M
16

You can check it here, https://github.com/angular/angular/blob/master/packages/zone.js/NON-STANDARD-APIS.md

The idea is to let rxjs run into correct zone in different cases.

zone.js also provide a rxjs patch to make sure rxjs Observable/Subscription/Operator run in correct zone. For details please refer to pull request 843. The following sample code describes the idea.

const constructorZone = Zone.current.fork({name: 'constructor'});
const subscriptionZone = Zone.current.fork({name: 'subscription'});
const operatorZone = Zone.current.fork({name: 'operator'});

let observable;
let subscriber;
constructorZone.run(() => {
  observable = new Observable((_subscriber) => {
    subscriber = _subscriber;
    console.log('current zone when construct observable:', 
      Zone.current.name); // will output constructor.
    return () => {
      console.log('current zone when unsubscribe observable:', 
      Zone.current.name); // will output constructor.
    }
  });
}); 

subscriptionZone.run(() => {
  observable.subscribe(() => {
    console.log('current zone when subscription next', 
      Zone.current.name); // will output subscription. 
  }, () => {
    console.log('current zone when subscription error', d 
      Zone.current.name); // will output subscription. 
  }, () => {
    console.log('current zone when subscription complete', 
      Zone.current.name); // will output subscription. 
  });
});

operatorZone.run(() => {
  observable.map(() => {
    console.log('current zone when map operator', Zone.current.name); 
    // will output operator. 
  });
});

Currently basically everything the rxjs API includes

  • Observable
  • Subscription
  • Subscriber
  • Operators
  • Scheduler

is patched, so each asynchronous call will run in the correct zone.

To answer your comment question.

No, it is not correct. Currently, without the patch, every callback will run inside or outside of angular zone depends on the emitter. It will have nothing to do with when the callback was created.

for example.

let sub;
ngZone.runOutsideAngular(() => {
   const observable = new Observable(subscriber => sub = subscriber));
   observable.subscribe(() => {
      // in ngzone
   });
});

ngZone.run(() => {
  sub.next(1);
});

in this case, the observable was created outside of angular zone, but the subscriber.next was called inside angular zone, so finally, the callback will still in angular zone.

with the patch, the callback will be out side of ngzone because it is created outside of ngzone.

Magnanimous answered 10/6, 2018 at 15:31 Comment(5)
So practical implication for me as angular developer would be: if I create observable outside of Angular zone and call map operator inside then without patch operator's callback will be called outside angular zone but with patch it will be called inside. Am I right?Dees
I updated my answer for your comment. you can check it.Magnanimous
I've created showcase - stackblitz.com/edit/angular-zone-rxjs-patch-test. Patch is included in polyfills.ts. Reload app after disabling/enabling the patch.Dees
Thank you for the demo, you are using rxjs 6, is that working as you expected? I have not tried rxjs 6, because patch only work for 5+ now.Magnanimous
A Stackblitz example with some more commentsCleghorn

© 2022 - 2024 — McMap. All rights reserved.