使用 Worklet 时使用 async/await 而不是回调
Using async/await instead of callback when using Worklet
我正在编写一个包装器 class 来隐藏使用 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 的回答的第 3 部分,我能够重写 class 如下:
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);
}
我认为以下三点可能对您有所帮助
Promises 不会 return 多个值,所以像请求消息这样的东西一旦 fulfilled/resolved 就不能再次触发,所以它不适合 request/post 多条消息。为此,您可以使用 Observables 或 RxJS
您可以使用 util.promisify
将 NodeJS 回调样式函数转换为这样的承诺
const { readFile } = require('fs')
const { promisify } = require('util')
const readFilePromise = promisify(fs.readFile)
readFilePromise('test.txt').then(console.log)
或手动创建包装函数,return 承诺在回调中 resolve/reject 围绕它们。
- 为了解决承诺块之外的承诺,您可以将 resolve/reject 保存为变量并稍后像这样调用它们
class MyClass {
requestSomething() {
return new Promise((resolve, reject) => {
this.resolve = resolve
this.reject = reject
})
}
onSomethingReturned(something) {
this.resolve(something)
}
}
我正在编写一个包装器 class 来隐藏使用 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 的回答的第 3 部分,我能够重写 class 如下:
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);
}
我认为以下三点可能对您有所帮助
Promises 不会 return 多个值,所以像请求消息这样的东西一旦 fulfilled/resolved 就不能再次触发,所以它不适合 request/post 多条消息。为此,您可以使用 Observables 或 RxJS
您可以使用
util.promisify
将 NodeJS 回调样式函数转换为这样的承诺
const { readFile } = require('fs')
const { promisify } = require('util')
const readFilePromise = promisify(fs.readFile)
readFilePromise('test.txt').then(console.log)
或手动创建包装函数,return 承诺在回调中 resolve/reject 围绕它们。
- 为了解决承诺块之外的承诺,您可以将 resolve/reject 保存为变量并稍后像这样调用它们
class MyClass {
requestSomething() {
return new Promise((resolve, reject) => {
this.resolve = resolve
this.reject = reject
})
}
onSomethingReturned(something) {
this.resolve(something)
}
}