В редакторе шаблона платежа СберБизнес бухгалтер правит назначение платежа и жмёт Ctrl+Z. Если каждая буква — отдельный шаг, отмена фразы «Оплата по счёту № 418» требует 21 нажатие.
Напишите класс History(initial, { limit = 50, mergeMs = 1000 } = {}). value — текущее значение. set(v) записывает новое значение; если оно равно текущему (===), ничего не происходит. undo() и redo() возвращают значение после шага; если шагать некуда, значение не меняется. canUndo() и canRedo() — есть ли куда шагать.
Склейка: если set пришёл не позже mergeMs после предыдущего set и между ними не было undo/redo, он не создаёт новый шаг, а заменяет последний. Время берите из Date.now().
Новый set после undo стирает ветку redo. Отменить можно не больше limit шагов: самые старые забываются.
В работе: Форма шаблона платежа: 12 полей, отмена работает по фразам, а не по буквам.
Пример 1: отдельные шаги и отмена
"", {"mergeMs": 0}, [[0, "set", "Оплата"], [10, "set", "Оплата по"], [20, "undo"], [30, "undo"], [40, "undo"]]["=Оплата", "=Оплата по", "undo:Оплата", "undo:", "undo:"]
Пример 2: быстрый набор — один шаг
"", {"mergeMs": 1000}, [[0, "set", "О"], [200, "set", "Оп"], [400, "set", "Опл"], [3000, "set", "Опл."], [3100, "undo"], [3200, "undo"]]["=О", "=Оп", "=Опл", "=Опл.", "undo:Опл", "undo:"]
History — тест вызывает её сам. Таймеры и Date в тестах ненастоящие: время идёт по команде теста, поэтому setTimeout на 5 секунд проверяется мгновенно. Тестов 8: 2 открыты выше, остальные приходят после старта подхода. Лимит — 2 с на тест.
class History { constructor(initial, { limit, mergeMs } = {}); value; set(v); undo(); redo(); canUndo(); canRedo() }
Источник: на задачах Сбера: шаблоны платежей в СберБизнес. Условие пересказано своими словами.
Ожидаемый ответ не нужен: покажем, что вернула функция.
Здесь появится результат отправки.