Несколько дней назад я разговаривал с выдающимся старшим инженером-программистом о реактивном программировании (RP), и он сказал мне, что нам это не нужно; он сказал, что у нас уже есть обещания, и их достаточно. Я должен сказать, что это был не первый раз, когда я слышал такое от разработчика, но я уже знал, почему большинство из них говорят это. Очень часто мы начинаем изучать фреймворк или то, как использовать библиотеку, не понимая сначала, как работают и взаимодействуют базовый язык программирования или связанные с ними технологии. Я вижу, что большинство разработчиков начинают путешествие по Angular, не зная и не понимая таких вещей, как Typescript, RP или даже JavaScript. Я понял, что мой товарищ-программист связал RP и ее главных героев, Observers и Observables, только с вызовами ajax на сервер, получением данных и выполнением каких-либо действий с ними. Если вы так думаете, вы непременно свяжете RP с обещаниями и скажете, что вам не нужен другой способ сделать это, и я не буду винить вас.

Еще раз, изучение Angular без недооценки RP и использование его (RP) только для создания сервисов, извлекающих данные с сервера, заставило кого-то поверить, что это все, о чем были Observers и Observables. Поэтому я решил создать три простых задачи, которые мой друг решил бы, используя обычный JavaScript и любую другую библиотеку или фреймворк, за исключением RxJS, который я собирался использовать для своих решений. Я вручил ему 3 задачи и сказал: «Мне бы хотелось, чтобы вы справились с этим лучше и чище без реактивного программирования», чтобы он мог взглянуть на ценность RP или я мог узнать что-то еще более интересное. «Еще одно, - сказал я, - вы, конечно, можете использовать Promises».

Пожалуйста, включите следующие две строки кода вверху вашего файла JavaScript, если вы хотите продолжить, после добавления тега script на свою HTML-страницу, указывающего на https://cdnjs.cloudflare.com/ajax/libs/ rxjs / 5.5.11 / Rx.min.js .

Проблема №1:

После трехкратного нажатия кнопки, после которого между каждым щелчком должна пройти не менее одной секунды, один раз напечатайте «Задача №1 решена» в консоли браузера. Дальнейшие клики не будут иметь никакого эффекта.

Мое решение:

Мы вытащили кнопку из DOM, используя ванильный JavasScript, и тут началось волшебство. Мы сделали клиентское событие Observable и использовали три оператора Observable, чтобы сказать: «Не выдавать значение, если предыдущее было передано менее секунды назад, подождите, пока продолжатся три излучаемых значения, возьмите только одно и это Это". Наконец, мы подписались на Observer, который выводит желаемый результат в консоль браузера, когда получает уведомление о переданном значении. Я не буду вдаваться в подробности, поскольку цель этой статьи не в том, чтобы объяснить RP, об этом уже написано много статей.

Подумайте об этом сейчас: если бы вы сделали это без RP, вам пришлось бы добавить переменную для отслеживания количества кликов, добавить if / else и, возможно, использовать setTimeout (который вам придется очистить вручную, потому что, если вы имеете дело с производственным приложением, я знаю, что вы не хотите, чтобы ваш код мог вызывать утечки памяти). Но знаете что, мне не нужно было беспокоиться ни об одной из этих трех вещей в моем коде, и я гарантирую, что в нем нет ошибок, как быстро вы можете быть уверены в этом в своем?

Задача № 2:

Выполните ajax-вызов API для получения некоторых данных, повторите вызов до трех раз в случае сбоя, но позволяя 2 секунды проходить между каждым вызовом ajax. Если три вызова завершились неудачно, напишите «Ошибка вызова API» в консоли браузера , если какой-либо из них завершился успешно, вместо этого покажите полученные данные.

Мое решение:

Код довольно понятен. Мы создаем Observable, который представляет вызов ajax, а затем используем несколько операторов для задержки каждой повторной попытки на 2 секунды, мы делаем только 3 попытки, и если все они терпят неудачу, мы бросаем наша ошибка. Наконец, мы подписываем наблюдателя, который знает, как справляться с успехом и неудачей. Подумайте еще раз, сколько еще кода это заняло бы без RP, и насколько больше это было бы подвержено ошибкам.

Задача № 3:

Отфильтруйте массив на основе ввода пользователя в текстовое поле по мере того, как пользователь вводит текст, но подождите одну секунду, прежде чем запускать фильтрацию, и отобразите отфильтрованный массив в консоли браузера.

Мое решение:

Мы получаем элемент input из DOM и делаем его событие keyup Observable. После этого мы сопоставляем его, чтобы получить текст в текстовом поле после того, как пользователь отпустил клавишу. Затем мы отбрасываем любое значение, испущенное менее чем через секунду после того, как было испущено предыдущее, и ограничиваем его повторное испускание, если текст в текстовом поле такой же, как был раньше. Наконец, мы подписываем Observer, который фильтрует массив на основе текущего ввода и выводит его в консоль браузера.

У меня есть одна интересная история, связанная с логикой этого последнего вызова. Однажды я видел презентацию кого-то из сотрудников Google, в которой они объясняли, насколько сложно им было кодировать функцию автозаполнения для своего продукта, когда им впервые приходилось это делать. То, что они считали очень простым, оказалось очень сложным, потому что им нужно было решить две интересные проблемы, с которыми они столкнулись. Во-первых, запуск запроса ajax к серверу для получения данных после каждого нажатия клавиши снижал производительность приложения, а во-вторых, характер асинхронного программирования заставлял более старые результаты переопределять более свежие результаты, создавая ужасный пользовательский опыт. Если бы только у них был RP для написания кода, очень похожего на этот последний, который мы написали, нужно было просто изменить фильтрацию массива для вызова ajax (и, конечно, обрабатывать некоторые другие реальные сценарии, такие как сбой или данные display) было бы намного проще выполнить задачу.

Недавно я слышал, как Мэтью Подвизоки, https://twitter.com/mattpodwysocki, сказал, что он написал код с использованием jQuery для достижения аналогичного результата (автозаполнение на основе результата вызова ajax), и для этого потребовалось ему нужно две страницы кода, чтобы сделать это. Я не сомневаюсь, что кто-то сможет сделать это с меньшими затратами, но мне бы хотелось посмотреть, будет ли это лучше и чище, чем решение RP.

Если вы разработчик на стороне сервера и считаете, что RP к вам не подходит, смело переходите непосредственно к последнему абзацу моей предыдущей статьи https://medium.com/@ericrey85/functional-reactive-programming-explained- in-a-simple-way-in-javascript-yes-in-a-simple-way-925b14cddf75 или просто перейдите на http://reactivex.io/ , и вы обнаружите, что ошиблись.

Если вы хотите увидеть еще одну статью, в которой эти три проблемы решаются с помощью функционального реактивного программирования (FRP), дайте мне знать в комментариях или по электронной почте на адрес [email protected]. Если вы хотите сначала узнать, что такое FRP, вы можете прочитать мою предыдущую статью, на которую я уже ссылался в предыдущем абзаце.

В конце истории я был очень рад видеть, что мой товарищ-программист влюбился в RP; хотя я должен признаться, я действительно хотел, чтобы он придумал что-то, чего я не знал или вообразил, что должно было поразить меня.

Удачного кодирования!