我找到了一个很棒的service用于在Ionic
中录制音频。
但至少有一件事我不明白:
例如,在第25行:
this.MediaPlugin.startRecord();
问题:为什么要调用this.MediaPlugin.startRecord()
而不是this.mediaPlugin.startRecord()
,其中this.mediaPlugin
是一个对象而MediaPlugin
是一个类?
如果类使用this.MediaPlugin
来执行操作,为什么它会在get
方法中返回一个对象?
完整代码:
import { Injectable } from '@angular/core';
import { MediaPlugin } from 'ionic-native';
export enum AudioRecorderState {
Ready,
Recording,
Recorded,
Playing
}
@Injectable()
export class AudioRecorder {
mediaPlugin: MediaPlugin = null;
state: AudioRecorderState = AudioRecorderState.Ready;
get MediaPlugin(): MediaPlugin {
if (this.mediaPlugin == null) {
this.mediaPlugin = new MediaPlugin('../Library/NoCloud/recording.wav');
}
return this.mediaPlugin;
}
startRecording() {
this.MediaPlugin.startRecord();
this.state = AudioRecorderState.Recording;
}
stopRecording() {
this.MediaPlugin.stopRecord();
this.state = AudioRecorderState.Recorded;
}
startPlayback() {
this.MediaPlugin.play();
this.state = AudioRecorderState.Playing;
}
stopPlayback() {
this.MediaPlugin.stop();
this.state = AudioRecorderState.Ready;
}
}
答案 0 :(得分:1)
this.MediaPlugin
是对get
的引用。使用这种语法,它将在第一次调用时构造MediaPlugin
,但在后面的调用中使用构造。
(这个解决方案对我来说似乎有点奇怪,因为仅仅使用AudioRecorder
类中的构造函数来初始化this.mediaPlugin
更有意义,然后使用{{1其他地方)
答案 1 :(得分:0)
首先,以下方法是一个getter,我猜它是尝试使用延迟初始化实现readonly属性。
get MediaPlugin(): MediaPlugin {
if (this.mediaPlugin == null) {
this.mediaPlugin = new MediaPlugin('../Library/NoCloud/recording.wav');
}
return this.mediaPlugin;
}
因此,当您第一次尝试访问this.MediaPlugin时,正在创建MediaPlugin的新实例。当您实例化AudioRecorder并且不使用它时(由于某些原因)它可以帮助您节省内存而不是立即创建MediaPlugin实例。 (见Lazy loading pattern)
回答你的问题:
为什么要调用this.MediaPlugin.startRecord()而不是 this.mediaPlugin.startRecord()其中this.mediaPlugin是一个对象和 MediaPlugin是一个类?
Typescript不提供任何常见的延迟加载机制,实现它的方法是使用getter方法创建私有属性(如在AudioRecorder类中)。
调用this.MediaPlugin.startRecord()
,你可以封装MediaPlugin实例的创建和操作逻辑。
答案 2 :(得分:0)
有人对命名约定搞砸了。该属性的名称应为mediaPlugin
,而不是MediaPlugin
。
名为MediaPlugin
的属性访问者的原因是,已存在名为mediaPlugin
的支持字段。
有些人认为应该将支持字段称为_mediaPlugin
。其他人则认为这会违反命名惯例。如果是后者,可以称之为mediaPluginField
。
class AudioRecorder {
mediaPluginField: MediaPlugin = null;
get mediaPlugin(): MediaPlugin {
if (this.mediaPluginField === null) {
this.mediaPluginField = new MediaPlugin('../Library/NoCloud/recording.wav');
}
return this.mediaPluginField;
}
}
然而,正如@Vladyslav Yefremov所指出的,可以说更好的选择是通过构造函数注入MediaPlugin
依赖项,或者从某种服务定位器中提取它。
class AudioRecorder {
constructor(private mediaPlugin: MediaPlugin) { }
}
或
class AudioRecorder {
private mediaPlugin: MediaPlugin;
constructor(mediaPlugin: MediaPlugin) {
this.mediaPlugin = mediaPlugin;
}
}
我没有立即看到需要懒惰地实例化媒体插件,因为录音机需要一个媒体插件来执行所有操作。
然而,可能是因为媒体插件在实例化时具有加载媒体文件的副作用。如果是这种情况,则媒体插件属性会被懒惰地实例化,以延迟资源的打开,直到实际需要它为止,即需要AudioRecorder时。