使用Worklet时使用async / await而不是回调

问题描述 投票:3回答:1

我正在编写一个包装类,隐藏了使用AudioWorklet的内部工作。使用worklet涉及通过消息端口在节点和处理器之间进行通信。

一旦在节点中运行的代码到达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我无法弄清楚如何将resolvePromise粘贴到this.awNode.port.onmessage。对我来说,似乎this.awNode.port.postMessagethis.awNode.port.onmessage之间的代码中断超出了同步性。

由于使用AudioWorklet已经打破了任何向后兼容性,因此可以使用最新的ECMAScript功能。

编辑

感谢Khaled Osman答案的第3部分,我能够按如下方式重写课程:

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);
}

javascript async-await web-worker
1个回答
1
投票

我认为有三件事可能会对你有所帮助

  1. Promise不会返回多个值,因此一旦满足/解决了请求消息之类的内容就无法再次触发,因此它不适合请求/发布多个消息。为此,您可以使用Observables或RxJS
  2. 您可以使用util.promisify将NodeJS回调样式函数转换为类似的承诺
const { readFile } = require('fs')
const { promisify } = require('util')
const readFilePromise = promisify(fs.readFile)

readFilePromise('test.txt').then(console.log)

或者手动创建包装函数,这些函数返回它们周围的promises,它们在回调中解析/拒绝。

  1. 为了解析promise块之外的promise,你可以将resolve / reject保存为变量,然后像这样调用它们
class MyClass {
  requestSomething() {
    return new Promise((resolve, reject) => {
      this.resolve = resolve
      this.reject = reject
    })
  }

  onSomethingReturned(something) {
    this.resolve(something)
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.