【问题标题】:Web MediaAPI - MediaRecorder : Adding AddEventListener with handler in parent class scope instead of inline callbackWeb MediaAPI - MediaRecorder:在父类范围内添加带有处理程序的 AddEventListener 而不是内联回调
【发布时间】:2020-04-14 05:52:27
【问题描述】:

在我的 Angular 项目中,我有一个有 2 个成员函数的类。在第一个函数中,我有 2 个级别的回调。在第一个回调中,我需要添加第二级事件回调。在这个第二级回调中,我需要能够调用顶级类的第二个成员函数。我尝试了https://www.pluralsight.com/guides/javascript-callbacks-variable-scope-problem 中建议的技巧。它对我不起作用。目前我正在尝试Angular2 - how to call component function from outside the app 谈论 ngZone 以公开组件成员函数。

我的代码详情:

我有一个用 Angular 8 编写的音频处理“AudioProcessingUtility”类。在它的 Init() 中,我正在初始化 MediaRecorder。我正在为“datavailable”事件添加一个监听器。此侦听器函数需要从“主”类调用我的实用程序函数。即它必须从回调进入父类的范围。

代码:

 export class AudioProcessingUtility  {
//integrated componet-level properties

//video conf specific properties
localAudioStreamStdObj: MediaStream;
mediaRecorder: any;
agoraService: any;
localStream: Stream; 

constructor() {}

private StreamInit() { //top-level member function to init

    this.localStream.init(() => { 

        this.agoraService.client.publish(this.localStream, function (err) { //This triggers "stream-published" event.
            console.log("Publish local stream error: " + err);
        });
        this.agoraService.client.on('stream-published', function (evt) {
            console.log("Publish local stream successfully");
            this.localAudioStreamStdObj = new MediaStream([evt.stream.getAudioTrack()]); //Specific details of media API
            this.mediaRecorder = new MediaRecorder(this.localAudioStreamStdObj, { mimeType: 'audio/webm' }); //Specific details of media API
            this.mediaRecorder.start(4000);
            this.mediaRecorder.addEventListener("dataavailable", event => { //Triggered every 4 seconds. 
                console.log("callbackfn: data vailable");
                console.log(event.data);
                //MY NEED
                this.audioProcessorCallback(event.data); //top-level member function be called
            }); 

            this.mediaRecorder.addEventListener("stop", () => {
            });
            ////end real time grab

        });
    }, function (err) {
        console.log("failed", err);
        });

}//end of stream Init function

public audioProcessorCallback(eventdatavailable) { //Top-level function to be called from 2nd-level callback
    console.log("My processing");
    //Do REST API calls. Based on internal states of the class, do specific processing
  }
 } //end of AudioProcessingUtility  

问题:

dataavailable 事件被触发。但我在以下几行中遇到错误。它给出错误 ERROR TypeError: this.audioProcessorCallback is not a function

     //MY NEED
     this.audioProcessorCallback(event.data); //top-level member function be called is not recognized. 

我明白这是因为 - 在回调内部,它无法找到“this context”。请建议我如何调用我的类函数,而不必将所有内容都放在内联回调函数中,这对我来说不实用。

编辑:我重写了问题以提供显示完整代码并更改了描述。提前致谢。

【问题讨论】:

  • 你应该使用箭头函数,因为函数中的this 没有引用词法this。此外,您在回调中返回的原因也不清楚:它什么也没做。
  • 我以为我创建了箭头函数。我刚刚编辑添加);。我的回调正在工作。但正如你所提到的,这并不是指“这个”。如何让它参考这个?还是打电话给班员?我读了一篇文章pluralsight.com/guides/…,它表明 return 会给出之前的上下文和调用。但是,正如您所提到的,它似乎什么也没做。请提出使用班级成员的最佳方式。
  • 返回函数时你想做什么?
  • 我正在尝试“弹出”“外部类上下文”。根据文章,它为我提供了“外部上下文”,即我的实用程序类的上下文,其中包含一些包含在类成员中的 REST API 调用。我打算在触发事件“datavailable”时调用该函数。我无法将所有代码复制到回调中,因为类中包含的 fag 和其他细节很少。
  • 为什么不能调用类中的方法?我还不清楚。这听起来更像是一个 XY 问题。

标签: angular typescript asynccallback web-mediarecorder


【解决方案1】:

我不确定为什么在回调中需要return。考虑一下:

client.on("stream-published", evt => {
  console.log("Publish local stream successfully");
  this.mediaRecorder.addEventListener("dataavailable", event => {
    console.log("callbackfn: data vailable");
    console.log("Calling this.audioprocessor(event)");
    this.audioprocessor(event);
  });
});

一旦callback 被触发,它将触发this.audioprocessor。由于您使用的是箭头函数,this 的上下文将是 class

【讨论】:

  • 我错过了在问题中添加另一个级别的回调。我现在已经更新了这个问题。即在回调里面,我注册了回调,需要调用类的函数。
  • > this.audioprocessor .. 这是你上课的方法吗?
  • 是的。它是类中的公共方法。
  • > this.mediaRecorder 这也是类上的方法吗?
  • 是的。它是类上的一个方法。我编辑了我原来的描述以更好地反映他的情况。谢谢。
【解决方案2】:

我的问题是由于上下文。从第 2 级的回调中,它无法看到“此上下文”,并且无法访问成员函数。我通过 ngZone 暴露了 Angular 组件。我从回调中调用它,就好像我从外部 javascript 函数中调用一样。答案基于Angular2 - how to call component function from outside the app

//Mycomponent.ts

import {  NgZone, OnDestroy } from '@angular/core';

constructor(
        //other params removed for clarity
      private _ngZone: NgZone
      )
      {
      //This is how I register with 'window'. 'audioProcessFn' is the alias for my member function.
       window['MycomponentRef'] = { component: this, zone: _ngZone, audioProcessFn: (value) => this.audioprocessor(value) };
      }

 ngOnDestroy() 
{
    window['MycomponentRef'] = null;
}

在我的回调中,代替

      //MY NEED
            this.audioProcessorCallback(event.data); //top-level member function be called
        }); 

我现在有这个代码 -

   /MY NEED
                    window['MycomponentRef'].zone.run(() => {
                        console.log("ngZone.run . Call getRealtime Emotion ");
                        window['MycomponentRef'].audioProcessFn(base64data );
                    })          
                }

            }); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 2011-09-12
    • 2022-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多