Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Losing zone in RxJS and fetch #31749

Closed
alvipeo opened this issue Mar 30, 2016 · 20 comments
Closed

Losing zone in RxJS and fetch #31749

alvipeo opened this issue Mar 30, 2016 · 20 comments
Assignees
Milestone

Comments

@alvipeo
Copy link

alvipeo commented Mar 30, 2016

For my angular 2 project I created a service that uploads files and I use fetch API there and RxJS. But it doesn't keep angular zone, here:

return uploadFileUri$
            .map(uri => {
                uploadFileUri = uri;
                return file.loadBlocksWithFileData();
            })
            .switch()
            .mergeMap((blk: IlgBlock) => {
[ ... some unrelated stuff ... ]
                console.log("Zone1: " + Zone.current.name);

                return fetch(putUri, reqOptions);
            }, (blk: IlgBlock, resp: Response, idx) => {
                console.log("Zone2: " + Zone.current.name);

                return [blk, resp];
            }, 1  // fetch ONE at a time
            )
[ ... other operators ...]

the output is:

Zone1: angular
Zone2: root

This shouldn't be like it I think. As a result, component's view doesn't ever get updated.

Also, once zone is lost it never gets back to 'angular'. So I see angular only the first time it runs.

zone: 0.6.8.

@alvipeo alvipeo changed the title Loosing zone in RxJS and fetch Losing zone in RxJS and fetch Mar 30, 2016
@QuentinFchx
Copy link
Contributor

I have the same issue with observables (RxJS).
I use switchMap, that gets an http observable as a return value and subsequent functions in the observable chains are not called.
It seems to happen whenever an xhr is implied (and I saw some changes around xhr in the recent commits..)
Everything was working as expected with 0.6.6, 0.6.8, and started breaking with 0.6.9.

@alvipeo
Copy link
Author

alvipeo commented Apr 6, 2016

What do you mean by "subsequent functions are not called"? Everything called in my case except these calls are not in the angular zone except for the very first operator.

@QuentinFchx
Copy link
Contributor

My issue was fixed by this commit angular/zone.js@c70f011. (0.6.10) does it fix yours ?

@alvipeo
Copy link
Author

alvipeo commented Apr 9, 2016

No, didn't fix it.

@alvipeo
Copy link
Author

alvipeo commented Apr 9, 2016

This is how I got it working - with 2 hacks:

                _uploadService
                    .uploadFiles$(this._selectedFiles)
                    .sample(Observable.interval(10))    // hack 1 !  (this actually forces the view to get updated)
                    .subscribe(
                    (arr: Array<IlgUploadFileData>) => {
                        //console.log(Zone.current.name);
                        this._selectedFiles = arr;
                    },
                    err => {
                        this.errorText = err;
                        this._uploadInProgress = false;
                    },
                    () => {
                        this.zone.run(() => {           // hack 2 !
                            //console.log(Zone.current.name);
                            this._uploadInProgress = false;
                            this._uploadComplete = true;

                            this.emitDoneEvent();
                        });
                    });

@jcestibariz
Copy link

I narrowed it down to a conflict with systemjs' system-polyfills.js (required by Angular2)

The code in the attached file works as expected but enabling system-polyfills.js breaks it.

test-zone.zip

@jcestibariz
Copy link

BTW trying to run Angular2's "Hello World" without system-polyfills.js in Chrome 50 (which has native Promises) results in this error:

es6-shim.js:2307 Uncaught RangeError: Maximum call stack size exceeded
Promise @ es6-shim.js:2307
r @ es6-shim.js:2093
then @ es6-shim.js:2499
scheduleQueueDrain @ angular2-polyfills.js:455
scheduleMicroTask @ angular2-polyfills.js:463
ZoneDelegate.scheduleTask @ angular2-polyfills.js:348
Zone.scheduleMicroTask @ angular2-polyfills.js:280
scheduleResolveOrReject @ angular2-polyfills.js:574
ZoneAwarePromise.then @ angular2-polyfills.js:649
(anonymous function) @ es6-shim.js:2131

@iignatov
Copy link

iignatov commented Apr 25, 2016

It seems that the issue still exists in zone.js 0.6.12.

More details are available in the following topic.

Relevant source code:

// Code that breaks Angular change detection:
nearbySearch(request: { location: any, radius: string, types: string[] }) {
  return Observable.create(observer => {
    if (this._places) {
      this._places.nearbySearch(request, (result, status) => {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
          observer.next(result);
          observer.complete();
        }
      });
    }
  });
}

// Code that works fine:
test() {
  return Observable.create(observer => {
    let result = [{place_id: 1}, {place_id: 2}, {place_id: 3}];
    setTimeout(() => {
      observer.next(result);
      observer.complete();
    }, 2000);
  });
}

onGetNear() {
  this.nearbySearch({ /* ... */ }).subscribe(res => {
    // The following logs 'root' instead of 'Angular'.
    console.log(Zone.current.name);
    // The view doesn't get updated:
    this.places = res;
  });
}

onGetTest() {
  this.test().subscribe(res => {
    // The following logs 'Angular'.
    console.log(Zone.current.name);
    // Updates the view as expected:
    this.places = res;
  });
}

@jcestibariz
Copy link

Looks like the problem has been fixed in the current version of Angular (angular2@2.0.0-beta.17, systemjs@0.19.27, zone.js@0.6.12), it no longer requires system-polyfills.js.

@fknop
Copy link
Contributor

fknop commented May 10, 2016

I still have the RangeError issue running angular2 beta 17, systemjs@0.19.25 and zone.js@0.6.12. The weird thing is, it was working fine just yesterday.

@Zaithe
Copy link

Zaithe commented Jun 1, 2016

Seems like this issue might be the same issue #357 i'm experiencing. I removed system-polyfills.js from the files being loaded but i'm still having the RangeError.

@jitsmaster
Copy link

This happens when 2 copies of zone running in the same place. Before was system-polyfill.

I run into the same issue when including zone.js in the same time. When 2 zone both monitor all promise calls, they will bounce off each other and causing stack overflow.

angular-polyfill always contains ng's own zone implementation. zone.js shouldn't be loaded separately.

@juanmendes
Copy link

I'll leave my experience here. When upgrading to rc-1, I forgot to include node_modules/core-js/client/shim.js and got this stack overflow.

@AMar4enko
Copy link

AMar4enko commented Oct 12, 2016

Experiencing this issue with angular-universal. My code looks similar to the following:

fetchApi() {
  console.log(Zone.current._name);
  this._http.get('/url')
    .map((value) => {
      console.log(Zone.current._name);
    })
    .toPromise()
    .then((response) => {
      console.log(Zone.current._name);
    });
}

I'm getting:
angular
root
angular

console output

@mleibman
Copy link

Got bitten by this as well.
I'm working on a system to collect Angular 2 app-wide routing latency metrics, and this is throwing a big wrench in my design. The callbacks should execute in the zone they're registered in (angular/zone.js#51 (comment)), but they are not. Unfortunately, requiring that we manually kick it back to the right zone (either by explicitly calling myZone.run() inside a .subscribe(), or by chaining an .observeOn(zoneAwareScheduler) is not feasible. Would it be possible to patch RxJS? Has anyone done that successfully?

@siegenthalerroger
Copy link

I appear to be having the same issue, also using an API that returns a promise within Angular (Atlassian connect library - .request returns a promise).

ngFors and bindings, etc are not being updated. Only after a click in the relevant area.

@JiaLiPassion
Copy link
Contributor

@siegenthalerroger , could you provide a reproduce repo?

@siegenthalerroger
Copy link

https://github.com/siegenthalerroger/zonejsissue/

Should do the trick. You'll have to run it within an Atlassian developer instance to see the effect of the AP object though. The whole thing is a bit of a mess because it's part of a larger project.

The issue is in the app.component.ts file: this.uS.getCurrentUser().subscribe(res => this.user = res.name); does not trigger an update in the html. A fix is using the ngZone provider and using zone.run(…) but it's a bit of a work around.

@JiaLiPassion JiaLiPassion transferred this issue from angular/zone.js Jul 21, 2019
@JiaLiPassion JiaLiPassion self-assigned this Jul 21, 2019
@ngbot ngbot bot added this to the needsTriage milestone Jul 21, 2019
@JiaLiPassion
Copy link
Contributor

Now we have a patch for fetch API, so this issue can be closed

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jun 28, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests