我正在编写一个包装类,它隐藏了使用AudioWorklet
的内部细节。使用工作线程需要通过消息端口在节点和处理器之间进行通信。
一旦在节点中运行的代码到达port.postMessage()
,节点中的脚本执行就会结束。当node.port.onmessage
(通过processor.port.postMessage
)触发时,节点中的代码可以恢复执行。
我可以通过使用回调函数让其正常工作。请参见下面的代码。
class HelloWorklet {
constructor(audioContext) {
audioContext.audioWorklet.addModule('helloprocessor.js').then(() => {
this.awNode = new AudioWorkletNode(audioContext, 'hello-processor');
this.awNode.port.onmessage = (event) => {
switch (event.data.action) {
case 'response message':
this.respondMessage(event.data);
break;
}
}
});
}
requestMessage = (callback) => {
this.awNode.port.postMessage({action: 'request message'});
this.callback = callback;
}
respondMessage = (data) => {
// some time consuming processing
let msg = data.msg + '!';
this.callback(msg);
}
}
let audioCtx = new AudioContext();
let helloNode = new HelloWorklet(audioCtx);
const showMessage = (msg) => {
// additional processing
console.log(msg);
}
const requestMessage = () => {
helloNode.requestMessage(showMessage);
}
以及处理器
class HelloProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.port.onmessage = (event) => {
switch (event.data.action) {
case 'request message':
this.port.postMessage({action: 'response message', msg: 'Hello world'});
break;
}
}
}
process(inputs, outputs, parameters) {
// required method, but irrelevant for this question
return true;
}
}
registerProcessor('hello-processor', HelloProcessor);
调用requestMessage()
会导致Hello world!
在控制台中打印出来。由于有时回调函数会降低代码的可读性,因此我想使用await
重写代码,如下所示:
async requestMessage = () => {
let msg = await helloNode.requestMessage;
// additional processing
console.log(msg);
}
试图重写 HelloWorklet.requestMessage
,但我无法弄清如何将 Promise
的 resolve
与 this.awNode.port.onmessage
连接起来。对我而言,代码在 this.awNode.port.postMessage
和 this.awNode.port.onmessage
之间的中断超出了异步操作范畴。
由于已经使用了 AudioWorklet
,因此可以使用最新的ECMAScript功能,这已经打破了任何向后兼容性。
编辑
感谢 Khaled Osman 答案的第三部分,我能够将类重写为以下形式:
class HelloWorklet {
constructor(audioContext) {
audioContext.audioWorklet.addModule('helloprocessor.js').then(() => {
this.awNode = new AudioWorkletNode(audioContext, 'hello-processor');
this.awNode.port.onmessage = (event) => {
switch (event.data.action) {
case 'response message':
this.respondMessage(event.data);
break;
}
}
});
}
requestMessage = () => {
return new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
this.awNode.port.postMessage({action: 'request message'});
})
}
respondMessage = (data) => {
// some time consuming processing
let msg = data.msg + '!';
this.resolve(msg);
}
}
let audioCtx = new AudioContext();
let helloNode = new HelloWorklet(audioCtx);
async function requestMessage() {
let msg = await helloNode.requestMessage();
// additional processing
console.log(msg);
}