2

I am currently developing an angular7-app, created it the standard way through CLI and started coding. Now I would like to record some audio which is no difficult thing in modern browsers. I am using the built-in browser functionalities of getUserMedia(). Now comes the problem: zone.js catches all calls to the then() callback and does not allow to execute the custom code inside.

BUT: There is the patch delivered with zone.js, so that this special callback is called: https://github.com/angular/zone.js/blob/master/dist/zone-patch-user-media.js

Unfortunately, this refers to a depreciated implementation of getUserMedia() (https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia). So this script does not work. I tried changing it but nothing works. The patch is called because console.log() is displayed and in the debugger, I can go through the function. I assume, that this might be a little change to execute the callback. In the debugger the callback is then again catched by a function in zone.js which, as I assume, should not be called when the patch works. My implementation is the same as here (https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia):

navigator.mediaDevices.getUserMedia(constraints).then(
function(stream) {
    /* use the stream */ 
}).catch(
function(err) { 
    /* handle the error */ 
});

So, what is the current way of getting the callback to work? Or am I getting the concept wrong? Or should I use some library from npm to record the audio?

Nico
  • 336
  • 3
  • 19

1 Answers1

4

As much as I know, zone.js should not cause problems if used with navigator methods, since they're well known and correctly patched. By the way, if you are sure of what you say, you can still use zone.runOutsideAngular to go out from a zone:

constructor(private zone: NgZone) { }

yourMethod() {
  this.zone.runOutsideAngular(() => {
    navigator.mediaDevices.getUserMedia(constraints)
      .then(stream => console.log(stream))
      .catch(err => console.error(err));
  });

}

If then you want to re-enter a zone, you can call:

this.zone.run(() => {
  // again inside a zone
});

But be aware that you need it only if you want to continue an async flow. The sync code will keep being executed inside a zone:

yourMethod() {
  // this is inside a zone

  this.zone.runOutsideAngular(() => {
    navigator.mediaDevices.getUserMedia(constraints)
      .then(stream => {

        // this is outside a zone

        this.zone.run(() => {

           // and again inside a zone

        });
      })
      .catch(err => console.error(err));
  });

 // this is still inside a zone

}
  • When clicking through debugger the next call clearly goes to zone.js where a function like 'catchThen' (can't remember the name because I am currently not at work) is called. Something is going on there. But I will try your suggestion and get back. Is there something like `zone.goInsideAngular` what I should call at the end of my script? – Nico May 17 '19 at 07:58
  • 1
    Thanks for your answer. I had time to check it and your provided solution (going outside the zone) works well. – Nico May 19 '19 at 17:09
  • Appreciate for saving my day!, was all trying to fix this with webrtc that never worked, – Naga Mar 25 '23 at 09:06