Упражнение с реактивным программированием

Я изучаю реактивное программирование с помощью RxJS, и у меня есть следующее упражнение:

  • Он начинается с пустого массива
  • При запуске приложения в массив вставляется новая Дата()
  • Каждый раз, когда вы нажимаете на экран, в конец массива вносится значение с датой, когда был сделан клик
  • Когда массив имеет 3 значения, выполните расчет: (массив [2].value() + массив [1].value() - массив [0])% 2
  • Если результат = 0, то выведите «Результат действителен».
  • Иначе ничего.
  • После вычисления массива, если добавляется новый элемент, первый элемент необходимо удалить, переместить остальные и поместить этот новый элемент в конец массива.

Пробовал с декларативным способом и с реактивным, но реактивный способ не убеждает меня в том, что он действительно реактивный, так как содержит много if/else и много логики в подписчике.

Мой вопрос: В функции training_1__v2_reactive соответствует ли код реактивному программированию?

function exercise_1__v1_imperative() {
    let values: Array<Date> = [];
    values.push(new Date());

    document.addEventListener(`click`, () => {
        values.push(new Date());
        console.info(`values: `, values);

        if (values.length === 3) {
            let a = values[0].valueOf(), b = values[1].valueOf(), c = values[2].valueOf();
            let result = (c - b + a) % 2;
            console.info(`result: `, result);

            if (result === 0) {
                console.info(`Resultado valido: `, result);
            }

            values.shift();
        }
    });
}

function exercise_1__v2_reactive() {
    const newDate$ = of(new Date().valueOf());
    // newDate$.subscribe(console.info);

    const clickDate$ = fromEvent(document, `click`).pipe(
        map(x => new Date())
    );

    clickDate$.pipe(
        startWith(new Date()),
        scan<Date, Array<Date>>((acc, value) => {
            if (acc.length === 3) {
                acc.shift();
            }

            acc.push(value);
            return acc;
        }, [])
    ).subscribe(values => {
        console.info(values);

        if (values.length === 3) {
            let a = values[0].valueOf(), b = values[1].valueOf(), c = values[2].valueOf();
            let result = (c - b + a) % 2;
            console.info(`result: `, result);

            if (result === 0) {
                console.info('Resultado valido: ', result);
            }
        }
    });
}

Я не понимаю, в чем твой вопрос.

zero298 27.06.2019 22:04

@zero298 вопрос обновлен!!

Marlonchosky 27.06.2019 22:18
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
228
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Да, ваша функция exercise_1__v2_reactive в порядке с точки зрения rxjs с небольшими улучшениями. Вам не нужно использовать startWith и использовать оператор filter только для создания массива длины 3. Я бы предложил следующее:

function exercise_1__v2_reactive() {
  fromEvent(document, 'click')
                  .pipe(
                    mapTo(new Date()),
                    scan((acc: any, val) => {

                        if (acc.length === 3) {
                          acc.shift();
                        }
                        acc.push(val);
                        return acc;
                    }, []),
                    filter(a => a.length === 3),
                    //Tap is just to check what my array is - But its not needed
                    tap(console.info),
                    map(values => {
                        const result = (values[2].valueOf() - values[1].valueOf() + values[0].valueOf()) % 2;

                        console.info(`result: `, result);

                        if (result === 0) {
                            return 'Result Valid';
                        }
                        return 'Result Invalid';
                    })
                  ).subscribe(console.info);
}

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

Интересный ответ. У меня вопрос по скану: может другого оператора можно? Я думал об использовании буферов, может ли это сработать?

Marlonchosky 28.06.2019 05:22

@Marlonchosky Я сомневаюсь, что операторы буфера могут быть здесь полезны, потому что операторы буфера выдают буферизованные элементы в соответствии с условием буфера. Хотя вы можете использовать его, но в конечном итоге вы получите императивный код внутри вашего конвейера оператора или подпишитесь. Задача состоит в том, чтобы отследить последние две даты. Я думаю, что scan оператор - ваш лучший друг здесь.

user2216584 28.06.2019 15:27

Спасибо за ответ. Да, я думал, что с буферами я мог бы испускать каждый раз, когда у меня есть 3 даты, но тогда проблема была бы в том, как сохранить последние 2 даты

Marlonchosky 28.06.2019 15:48

После изучения операторов RxJS решение можно выполнить с помощью оператора bufferCount, передав его в качестве параметров bufferCount(3, 1), второй параметр указывает, когда запускать новый буфер, что в данном случае будет выполняться при каждом нажатии:

fromEvent(document, 'click').pipe(
  map(_ => new Date()),
  startWith(new Date()),
  bufferCount(3, 1),
  map(([a, b, c]) => (c.valueOf() - b.valueOf() + a.valueOf()) % 2),
  tap(val => console.info('TAPPING: ', val)),
  filter(x => x === 0)
).subscribe(valid => {
  console.info('Result valid')
});

Решение находится в этом URL: https://stackblitz.com/edit/rxjs-q3aneg

Другие вопросы по теме