Как стать автором
Обновить

Комментарии 20

Честно говоря ничего понятнее не стало про эти потоки, в чем разница/выгода например в сравнении с короутинами в том же питоне (async/await)?
async/await используются когда нужно получить только одно значение.
Если их много — то вместа множества await лучше использовать Observable.
Для получения нескольких значений можно использовать асинхронные генераторы.

Тут же суть скорее в том, что корутины не обладают тем самым свойством реактивности. Они не способны реагировать на поступающие события, а могут только активно запрашивать данные из источника. Чтобы поверх них реализовать реактивность, нужна отдельная блокирующая очередь сообщений, но даже в таком случае логика обработки данных будет инвертированной.
Чего это корутины не обладают? Это не от них зависит, если источник умеет пушить уведомления, то короутины могут отрабатывать по приходу сообщения.
Им для этого потребуется дополнительная структура, которая будет накапливать в себе события и операции запроса очередного события, и будет сопоставлять их друг с другом. Без подобного преобразователя обрабатывать поступающие сообщения корутины в общем случае не могут.

Ну и нагрузка на память от такого использования корутин будет куда больше, ведь на каждый шаг обработки события требуется несколько уникальных объектов.

Давайте на примере. У вас строка поиска, которая должна предлагать варианты автозаполнения, подгруженные с сервака. Наивная имплементация делается просто — при изменении строки делать запрос, возвращать результат через колбек/Promise/Task/что-там-awaitable-в-вашем-языке.
Теперь несколько моментов (допустим набираю habr):


  1. не хочется дергать запрос на каждый новую букву, нужен какой-то debounce (искать по habr, не по h,ha,hab,habr)
  2. не хочется дергать сервер совсем, если человек вбил букву, понял, что ошибся и удалил ее
  3. порядок выполнения — что если я делаю два запроса и второй выполняется до того как выполнился первый
  4. если хочется немного разгрузить сервис, можно добавить поддержку отмены запроса. Например, вбил 'h', запрос пошел, долго думает, вбил 'ha', abort первого запроса, второй запрос пошел, умный сервер может прибить первый запрос в базу и не отдавать ответ в никуда (CancellationToken в .NET).

Решение на Rx (в JS):


const stream =
  fromEvent(element, 'keyup').pipe(
    map(x => x.target.value),
    debounceTime(2000),
    distinctUntilChanged(),
    switchMap(x => ajax.get('http://service/term?q='+x)),
  )
.subscribe(console.log)

Я плохо знаком с питоном, можеть быть у вас там еще красивее это решается. Пример скорее про async/await в JS или .NET

Уже чуток понятнее, хотя задача весьма специфическая, не уверен, что таких случаем значительное количество.

Отличный пример, наконец-то понятно и на практике. А не сферические обзервабле в вакууме. Пойду искать как сделать этот debounce для сигнала в моем поделим на Qt.

НЛО прилетело и опубликовало эту надпись здесь
С какими именно и в каком языке программирования?
Тут важен контекст, так как поток можно перевести как thread, или подумать что речь идет, например, о java stream API.
НЛО прилетело и опубликовало эту надпись здесь
1) субъективно легче использовать, больше функций из коробки, более легкая обработка слияний потоков (разные варианты — flatMap, switchMap, concatMap, предлагающие разные варианты на все случаи жизни)
2) сходное API в разных языках (ну и можно один и тот же код шарить между клиентом и сервером, например)
3) стримы как будто бы больше ориентированы на работу с потоками данных, всякие кодировки, буферы и т.д. Rx же — потоками событий/состояний системы (в качестве входного потока можно использовать например setInterval). Хорошо стакается, например, с Redux
[быстро читает документацию к стримам в ноде]
По назначению:
Стримы в ноде больше предназначены для IO операций — взять данные из read потока и сразу записать во write поток по частям (chunk).
Rx больше для трансформации и построения сложных цепочек событий.

По сути:
Стримы это скорее pull коллеции. У них можно вызвать read что-бы, например, прочитать следующую часть файла.
Rx — push коллекции, которые сами уведомляют когда что-то происходит.
в стримы можно писать.

Не работал с реактивными компонентами, но скорее всего выход одного компонента можно перенаправить на вход другого в одну строчку.

Отличия от стримов в ноде:

1. У стримов нет такого набора комбинаторов из коробки;
2. У стрима не может быть нескольких читателей;
3. Стримы не распространяют ошибки по конвейеру автоматически;
4. Стримы поддерживают backpressure, в отличии от rx.

Ключевое отличие в том, что стримы поддерживают связь в обе стороны от читателя к писателю и обратно. В случае Observable связь только односторонняя от читателя к писателю. Именно поэтому backpressure здесь реализовать не тривиально.

«В отличие от обычных объектов, акторы не могут вызывать методы друг друга.
Акторы могут передавать информацию только через неизменяемые сообщения»

Это именно те объекты и то ООП, которое придумал Алан Кей.
Разве классическое понимание ООП предполагает декларативный подход?
А что вообще такое декларативный подход? Как нам отличить его от другого подхода? Вот console.log() — это декларативный подход или нет?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий