Использование async/await вместо обратного вызова при использовании Worklet

Я пишу класс-оболочку, скрывающий внутренности работы с 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.info(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.info(msg);
}

Пытаясь переписать HelloWorklet.requestMessage, я не могу понять, как приклеить resolvePromise к this.awNode.port.onmessage. Мне кажется, что прерывание кода между this.awNode.port.postMessage и this.awNode.port.onmessage выходит за рамки асинхронности.

Поскольку использование AudioWorklet уже нарушает обратную совместимость, можно использовать последние функции ECMAScript.

редактировать

Благодаря части 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.info(msg);
}

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
0
218
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, есть три вещи, которые могут вам помочь

  1. Обещания не возвращают несколько значений, поэтому что-то вроде сообщения запроса не может быть запущено снова после его выполнения/разрешения, поэтому оно не подходит для запроса/отправки нескольких сообщений. Для этого вы можете использовать Observables или RxJS.

  2. Вы можете использовать util.promisify для преобразования функций стиля обратного вызова NodeJS в такие промисы

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

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

или вручную создавать функции-оболочки, которые возвращают промисы вокруг них, которые разрешают/отклоняют внутри обратных вызовов.

  1. Для разрешения обещания за пределами блока обещания вы можете сохранить разрешение/отклонение как переменные и вызывать их позже, например, так
class MyClass {
  requestSomething() {
    return new Promise((resolve, reject) => {
      this.resolve = resolve
      this.reject = reject
    })
  }

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

Другие вопросы по теме