使用Worklet时使用异步/等待而不是回调

时间:2019-04-26 15:17:26

标签: javascript async-await web-worker

我正在编写一个包装器类,隐藏了使用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,但我不知道如何将resolve的{​​{1}}粘到Promise上。在我看来,this.awNode.port.onmessagethis.awNode.port.postMessage之间的代码中断似乎超出了异步性。

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

修改

多亏了Khaled Osman的答案的第3部分,我得以按如下方式重写该类:

this.awNode.port.onmessage

1 个答案:

答案 0 :(得分:1)

我认为有三件事可能对您有帮助

  1. Promise不会返回多个值,因此一旦完成/解决了请求消息之类的事情就无法再次将其触发,因此它不适合请求/发布多个消息。为此,您可以使用Observables或RxJS

  2. 您可以使用<script> export default { name: 'app', data () { return { amount: { active: false, name: this.$i18n.t('key_name'), value: this.$i18n.t('key_value') } } }, watch: { this.$i18n.locale (val) { this.amount.active = true } } } </script> 将NodeJS回调样式函数转换为类似的Promise

util.promisify

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

  1. 要在promise的范围之外解析promise,您可以将resolve / reject保存为变量,然后像这样调用它们
const { readFile } = require('fs')
const { promisify } = require('util')
const readFilePromise = promisify(fs.readFile)

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