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

[PLAT-6697] Prevent excess change detection cycles #1861

Merged
merged 8 commits into from
Nov 9, 2022
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

## v8.0.0 (TBD)

### Changes
### Fixed
- (plugin-angular) Prevent excess change detection cycles when calling `Bugsnag.notify` [#1861](https://github.com/bugsnag/bugsnag-js/pull/1861)

### Changed

- (plugin-navigation-breadcrumbs) calling `pushState` or `replaceState` no longer triggers a new session when `autoTrackSessions` is enabled [#1820](https://github.com/bugsnag/bugsnag-js/pull/1820)

Expand Down
26 changes: 26 additions & 0 deletions packages/plugin-angular/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { ErrorHandler, Injectable } from '@angular/core'
import Bugsnag, { Client, Plugin } from '@bugsnag/js'

// angular uses zones to watch for changes in asynchronous tasks so it can
// update the UI in response
// Bugsnag uses a lot of asynchronous tasks when notifying, which trigger change
// detection multiple times. This causes a potential performance problem, so we
// need to run `notify` outside of the current zone if zones are being used
// see https://angular.io/guide/zone
declare const Zone: any

// zones are optional, so we need to detect if they are being used
// see https://angular.io/guide/zone#noopzone
const isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.current

@Injectable()
export class BugsnagErrorHandler extends ErrorHandler {
public bugsnagClient: Client;
Expand Down Expand Up @@ -42,6 +54,20 @@ export class BugsnagErrorHandler extends ErrorHandler {

const plugin: Plugin = {
load: (client: Client): ErrorHandler => {
const originalNotify = client._notify

client._notify = function (event) {
if (isNgZoneEnabled) {
// run notify in the root zone to avoid triggering change detection
Zone.root.run(() => {
originalNotify(event)
})
} else {
// if zones are not enabled, change detection will not run anyway
originalNotify(event)
gingerbenw marked this conversation as resolved.
Show resolved Hide resolved
gingerbenw marked this conversation as resolved.
Show resolved Hide resolved
}
}

return new BugsnagErrorHandler(client)
},
name: 'Angular'
Expand Down