Use cases/Local draft restore — сохранение черновика локально
Use cases · 15 操
Local draft restore — сохранение черновика локально
Паттерн
Пользователь заполнил половину длинной формы и случайно закрыл вкладку. При следующем открытии приложение должно вернуть его черновик. При этом писать в localStorage на каждое нажатие клавиши — расточительно.
Какую проблему решаем
Нужно решить две задачи одним потоком: прочитать сохранённый черновик при старте и сохранять новые изменения с разумной частотой. Императивно эти задачи разъезжаются по разным методам компонента, и легко забыть, например, что в private-режиме localStorage кидает исключение.
Операторы и зачем они нужны
defer — читает storage только в момент subscribe (а не при импорте модуля). Это важно для SSR.
startWith — сразу отдаёт восстановленный draft как начальное значение формы.
throttleTime с trailing — ограничивает частоту записи, но гарантирует, что последнее значение всё-таки сохранится.
tap — выполняет сам side effect записи, не меняя данные.
Подводные камни
debounceTime вместо throttle — если пользователь закроет вкладку до паузы, последнее изменение не сохранится. Throttle с trailing решает эту проблему.
auditTime не отдаёт leading-значение — UI задержится на пустой форме. Применяйте его только к самому сохранению, не к отображению.
localStorage может бросать исключения (приватный режим, переполнение) — оборачивайте в try/catch или превращайте в Observable с catchError.
Что в итоге получаем
Форма мгновенно показывает восстановленный черновик, а storage пишется редко и предсказуемо. Один поток отвечает за всю работу с черновиком.