|
JavaScript. Как переделать EventEmitter на генератор? | ☑ | ||
---|---|---|---|---|
0
Вафель
23.05.17
✎
10:13
|
Есть объект генерирующий события (EventEmitter)
obj.on('data', f(data)) В событие поступают допустим числа 1..10, т.е. f(1), f(2), ...f(10) Можно ли как то такой EventEmitter переделать на генератор, чтобы писать код типа let dataGenerator = createGenerator(obj); for (let i of dataGenerator) { console.log(i) } |
|||
1
Вафель
23.05.17
✎
10:13
|
Для одиночных событий, такое легко переделывается на промисы
obj.on('end', f(data)) function onEnd(obj){ return new Promise((resolve) => { obj.on('end', (data) => resolve(data)) }); } и теперь можно писать data = await onEnd(obj); |
|||
2
Serginio1
23.05.17
✎
10:23
|
||||
3
Serginio1
23.05.17
✎
10:25
|
О вообще смотри на библиотеку RxJs
Там как раз работа с событиями как с потоком событий с применением аналога Linq |
|||
4
Вафель
23.05.17
✎
10:26
|
(3) А можешь пример кода написать, а то я как то не дохожу сам
|
|||
5
Asmody
23.05.17
✎
10:42
|
(0) Я не понял, что генератор должен вернуть
|
|||
6
Вафель
23.05.17
✎
10:44
|
(5) Должен возвращать, то что приходит в событие on('data')
|
|||
8
Asmody
23.05.17
✎
10:47
|
(6) Ну, ты можешь так же елдить промис. Только что потом с этой пачкой промисов делать?
|
|||
9
Вафель
23.05.17
✎
10:47
|
Классический пример (хотя и не мой) - это асинхронное построчное чтение файла
fs = reqire('fs'); f = fs.readFile('C:/tmp/text.txt'); f.on('data', (data) => {}) |
|||
11
Вафель
23.05.17
✎
10:48
|
(8) Хочется как обычно в цикле обходить
|
|||
13
Asmody
23.05.17
✎
10:49
|
Просто из контекста неясно, зачем так заморачиваться
|
|||
14
Вафель
23.05.17
✎
10:50
|
(13) Ради красоты кода. Так то задача уже решена на колбэках
|
|||
16
Вафель
23.05.17
✎
10:51
|
(15) Не будем это обсуждать в данной ветке
|
|||
17
Asmody
23.05.17
✎
10:52
|
Есть вот такая хрень https://github.com/tj/co
Но сам не пробовал, врать не буду. |
|||
18
Вафель
23.05.17
✎
10:53
|
(17) Я это читал, но как это применить так и не осилил
|
|||
19
Asmody
23.05.17
✎
10:57
|
Да хз. Ну типа
const createGenerator = obj => { return function* () { yield new Promise(resolve => { obj.on('end', data => resolve(data)) } } } |
|||
20
Serginio1
23.05.17
✎
11:01
|
||||
21
Вафель
23.05.17
✎
11:04
|
(19) А как тогда воспользоваться такой штукой?
|
|||
22
Asmody
23.05.17
✎
11:21
|
(21) типа так:
let gen = createGenerator(obj) for (let p of gen()) { // p - это Promise p.then(d => console.log(d)) } |
|||
23
Вафель
23.05.17
✎
11:29
|
(22) в данном случае
d - EventEmitter |
|||
24
Asmody
23.05.17
✎
11:33
|
(23) ну, это уже зависит от твоего obj.
|
|||
25
Вафель
23.05.17
✎
11:33
|
(23) Вру, приходи сообщение, но только 1 раз
|
|||
26
Вафель
23.05.17
✎
11:34
|
Да действительно и должен приходить эвент эмиттер, но явно больше чем 1 раз
|
|||
27
Вафель
23.05.17
✎
12:29
|
Вот такой вот код получился. Красивее уже не делается
https://gist.github.com/a-sitnikov/3f222788490ff5a54d1057258262476c |
|||
28
Asmody
23.05.17
✎
13:01
|
Вот это
await imapConnect(imap); await openInbox('INBOX/заявки'); я так понимаю, будет синхронно выполняться? |
|||
29
Asmody
23.05.17
✎
13:02
|
И еще я пока не понимаю, что в синтаксисе async/await будет в resolve
|
|||
30
Вафель
23.05.17
✎
13:02
|
(28) а как же еще.
Нельзя же открыть папку не подключившись вначале |
|||
31
Вафель
23.05.17
✎
13:04
|
(29) неопределено конечно же
|
|||
32
Serginio1
23.05.17
✎
16:17
|
(28) не синхронно, а последовательно.
Можно запустить две задачи и подождать асинхронно завершения 2 х задач. https://habrahabr.ru/post/282477/ let [firs,second] = await Promise.all([imapConnect(imap), openInbox('INBOX/заявки')]); |
|||
33
Serginio1
23.05.17
✎
16:20
|
(29) resolve это безошибочное завершение задачи.
В противном случае будет выкинута ошибка которую нужно ловить. Смотри https://habrahabr.ru/post/282477/ |
|||
34
Вафель
23.05.17
✎
16:21
|
(32) Так это не параллельные задачи. 2 зависит от 1
|
|||
35
Serginio1
23.05.17
✎
16:53
|
(34) Асинхронность и параллельность не одно и тоже.
Задачи выполняются последовательно, но асинхронно. Асинхронность заключается в тос, что при вызове await, поток возвращается в пул где может выполнять другие задачи из очереди. При окончании задачи резултьтат ставится в очередь и задача начинает выполнятся с места await. Внутри конечный автомат . Поэтому ты можешь использовать await в циклах, рекурсиях итд |
|||
36
Вафель
23.05.17
✎
16:59
|
Ладно пусть не параллельно.
Нов чем преимущество такого написания кода? |
|||
37
Asmody
23.05.17
✎
17:09
|
(33) Я знаю, как работает промис. Я спросил, по-сути, где в случае await писать то, что было в then()
|
|||
38
Вафель
23.05.17
✎
17:10
|
(37) Все что дальше идет - это как бы виртуальный then
|
|||
39
Asmody
23.05.17
✎
17:11
|
(32) Кстати, в этом случае так делать нельзя. Promise.all() не регламентирует порядок выполнения промисов. А у него четко: сначала соединяемся, потом открываем папку.
|
|||
40
Asmody
23.05.17
✎
17:12
|
(38) Да, я почитал уже, что await возвращает значение из вызова resolve.
|
|||
41
Вафель
23.05.17
✎
17:13
|
Если нужно внутри цикла писать, то незаменимая вещь.
Например прервать цикл по асинхронному условию |
|||
42
Garykom
гуру
23.05.17
✎
17:31
|
асинхронное условие и прерывание цикла это блин
|
|||
43
Garykom
гуру
23.05.17
✎
17:33
|
действительно чем то напоминает "Копайте пока здесь!!! А я схожу и узнаю где нужно!"
|
|||
44
Вафель
23.05.17
✎
17:35
|
(42) Ну а как еще? Сначала разрешить для всех элементов цикла, а потом проверять7
|
|||
45
Serginio1
23.05.17
✎
17:36
|
(40) Я привел пример когда последовательность не важна, а нужно выполнить параллельно.
(36) Еще раз при выполнение задач например запрос к базе данных, HTTP запросе это долгие операции которые будут блокировать поток. Вообще асинхронность больше нужна на сервере где есть пул потоков и нужно не блокировать поток за ненадобностью, а быстрее отдавать его в пул. При этом общая производительность выше. Для клиента не столь важно, но тоже не стоит блокировать рабочий поток и поддерживать единообразие. Например в .Net Core для асинхронных методов не синхронных аналогов. Нужно дополнительно использовать примитивы сихпронизации |
|||
46
Вафель
23.05.17
✎
17:36
|
Например найти первую строчку в файле содержащую текст.
Причем строчки приходят асинхронно |
|||
47
Asmody
23.05.17
✎
17:37
|
(42) "Блин" — это когда у тебя любой поход в БД, например, асинхронный. А жить как-то надо.
|
|||
48
Garykom
гуру
23.05.17
✎
18:11
|
(46) "асинхронно" приходят те которые ищем или "строчки текста" среди которых ищем?
|
|||
49
Serginio1
23.05.17
✎
18:11
|
(47) Можно через Promise.all запустить две задачи.
Одна задача на завершение по таймеру, а вторя долгая операция. Если первая задача завершилась раньше, то вторую задачу можно и не ждать https://ru.stackoverflow.com/questions/583438/%d0%a2%d0%be%d1%87%d0%bd%d0%be%d0%b5-%d0%bf%d0%be%d0%b2%d1%82%d0%be%d1%80%d0%bd%d0%be%d0%b5-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-%d1%86%d0%b8%d0%ba%d0%bb%d0%b0-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bf%d1%80%d0%be%d0%bc%d0%b5%d0%b6%d1%83%d1%82%d0%be%d0%ba-%d0%b2%d1%80%d0%b5%d0%bc%d0%b5%d0%bd%d0%b8-%d0%bf%d0%be%d1%81%d0%bb%d0%b5-%d0%b5%d0%b3/583827#583827 |
|||
50
Asmody
24.05.17
✎
09:12
|
(49) Ты путаешь Promise.all и Promise.race
|
|||
51
Serginio1
25.05.17
✎
14:56
|
(50) Да прошу прощения. В .Net Task.WhenAny
Сейчас на TS не пишу. Забываю |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |