У меня есть фоновый процесс, написанный в node.js, который использует EventEmitter следующим образом:
var event = { returnValue: undefined };
eventEmitter.emit('name', event, argument);
return event.returnValue; // Example of doing things with event.returnValue.
Другой конец мероприятия:
eventEmitter.on('name', (event, argument) => {
var returnValue = await asyncMethod(); // <- This method returns a Promise, so I could use await if possible or some other solution.
event.returnValue = returnValue;
});
Я пытался найти элегантное решение для использования асинхронных методов, но, поскольку EventEmitter не поддерживает асинхронные функции вообще не могу использовать await в функции или что-то подобное.
Одним из решений может быть установка returnValue на обещание, но это быстро становится непрактичным, особенно потому, что некоторые из моих функций повторяются через несколько асинхронных функций.
Мне нужно, чтобы весь код завершился правильно, прежде чем первый блок кода продолжится и попытается использовать event.returnValue.
Единственное мое решение - использовать стороннюю "синхронизацию", или никто в node.js не задумывался об этой проблеме?
Для меня нет никаких проблем, если поток заблокирован во время выполнения, поскольку это фоновый процесс без какого-либо графического интерфейса.
"Одним из решений может быть установка returnValue на обещание." - да, так и должно быть. Как вы думаете, почему это становится непрактичным? Вы можете привести пример этой «итерации через несколько асинхронных функций»?
@Bergi Код быстро становится загроможденным, если у меня есть несколько функций, возвращающих обещания, или повторение некоторого списка или массива, вызывающего асинхронную функцию внутри цикла.
@einord Вы имеете в виду, в обратном вызове одиночного события? Или вы говорите об установке нескольких прослушивателей событий? Если первое, вы можете тривиально построить единое обещание для всего, что делается с помощью цепочек then, синтаксиса async / await или Promise.all.
@Bergi, напишите ответ, показывающий это, если знаете простой способ :)
@einord Я просто знаю, что обещания - это простой способ, но я не могу привести конкретный пример нескольких функций, если я не знаю вашу точную проблему
@Bergi Проблема, когда вызывается несколько асинхронных функций, может выглядеть как его: { var items = []; item[0] = asyncMethod1();item[1] = asyncMethod2(); event.returnValue = items; /* <- This must be done in sync, since EventEmitter does not seem to support asynchronous code at all */ }
@einord event.returnValue = Promise.all(items), значит, это так.
@Bergi Отлично! Это работает для массивов. А как насчет более сложных объектов с большим количеством данных, часть из которых должна поступать из асинхронной функции? Пример: { var returnItem = { name: 'foo' }; returnItem.moreStuff = asyncMethod1(); event.ReturnValue = returnItem; }. Это сработает, но непрактично, поскольку любой код, пытающийся использовать returnItem, должен знать, что нужно ждать определенных значений.
@einord Promise.all(['foo', asyncMethod1(), …]).then(([name, moreStuff, …]) => ({name, moreStuff, …})) (или поместите сразу доступный материал в литерал объекта в обработчике then). Вы также можете использовать async / await для последовательного воспроизведения.
@Bergi - .then(() => {}) не вызывается асинхронно? Если так, я все еще не выбраюсь из "ада обратных вызовов", а также имею довольно запутанный код.
@einord Да, он создает объект, когда готовы все индивидуальные значения. Здесь нет ада обратных вызовов, он не гнездится бесконечно - обещания создают цепочку.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Поскольку на самом деле, кажется, не существует никакого интуитивного способа дождаться синхронного разрешения Promise без обратных вызовов или использовать EventEmitter с асинхронными обратными вызовами, Я написал свой простой EventEmitter, содержащий массив, и настраиваемые методы on и emit.
Он правильно обрабатывает асинхронные функции, используемые в качестве параметров, поэтому я могу использовать его следующим образом:
asyncEmitter.on('name', async (event, argument) => {
event.argument = await asyncMethod(); // Nice and clean code!
});
Конечно, я мог бы развить его дальше, создав функцию once и так далее, но на самом деле я полагаюсь только на on и emit.
Интересно, почему команда узлов еще не решила эту проблему?
Не совсем понятно, что вы имеете в виду под
One solution could be to set returnValue to a Promise, but that quickly becomes impractical, specially since some of my functions iterate through multiple asynchronous functions.и почему это проблема.