Имя: Пароль:
IT
Веб-мастеринг
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
50 Asmody
 
24.05.17
09:12
(49) Ты путаешь Promise.all и Promise.race
51 Serginio1
 
25.05.17
14:56
(50) Да прошу прощения. В .Net Task.WhenAny
Сейчас на TS не пишу. Забываю