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

标签 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 我不知道如何将 Promiseresolve 粘附到 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);
}

最佳答案

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

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

  2. 您可以使用 util.promisify 将 NodeJS 回调样式函数转换为这样的 promise

const { readFile } = require('fs')
const { promisify } = require('util')
const readFilePromise = promisify(fs.readFile)

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

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

  1. 为了在 promise block 之外解决 promise ,您可以将解决/拒绝保存为变量,稍后像这样调用它们
class MyClass {
  requestSomething() {
    return new Promise((resolve, reject) => {
      this.resolve = resolve
      this.reject = reject
    })
  }

  onSomethingReturned(something) {
    this.resolve(something)
  }
}

关于javascript - 使用 Worklet 时使用 async/await 而不是回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55870560/

相关文章:

javascript - while 循环的意外输出

javascript - 庞大函数的开销是多少?

javascript - Backbone.js:通过模板嵌套 View

c# - 如何正确阻止异步代码?

c# - 是否可以使对象构造异步?

javascript - 结合 browserify 和 WebWorker

javascript - ImportModuleError","errorMessage":"Error: Cannot find module while using Netlify lambda functions with dependencies

java - Java 开发人员理解 C# “async/await” 模式

javascript - 两个 javascript webworker 连续打印输出 - 为什么不同时呢?

javascript - HTML5 Web Workers 获得巨额 md5 总和