Comments 22
Доходчиво изложено, спасибо. Насколько я понимаю, у варианта с блокировкой кнопки также недостаток в том что шибко умный юзер может дергать API через Postman и тем самым обходить блок кнопки на фронте.
В синхронном сценарии есть проблемка, между шагами 1 и 2 в браузерной реализации есть место для состояния гонки:
1. Пользователь нажимает кнопку Перевести
2. Кнопка становится неактивной
Запрос уходит на сервер, интерфейс ждёт ответ
Обработчикам в js требуется небольшое время на то, чтобы сделать кнопку неактивной.
Престарелые мышки у пользователей могут выдавать несколько кликов вместо одного из-за эффекта дребезга контакта. Время между событиями составляет единицы милисекунд.
Описанный синхронный подход не защищает от этой гонки.
Вниманимательно слушаю почему эта конструкция не будет работать? 👀
button.addEventListener('click', () => {
button.disabled = true; // 1. Сначала выключаем
sendData(); // 2. Потом отправляем
});
Пытаюсь найти банк, но тут ни слова, хотя есть пару где есть такая беда
Вы прошли собес в итоге? Вам сделали оффер?
У вас алгоритм для идемпотентности некорректный. Если вы генерируете уникальный ключ на клиенте при нажатии кнопки, то повторные нажатия дадут разные уникальные ключи и пройдут две оплаты.
ключ будем генерить до отправки запроса, и если параметры запроса не меняются, то и ключ не изменится
Ну ка, какие у вас будут параметры, которые формируют ключ? Сумма, отправитель и получатель? Тогда точно такая же отправка средств будет заблокирована, хотя по факту это именно другой перевод.
Банально timestamp генерации формы даст уникальность
в асинхронном варианте вся проблема в том, кто решает новый это запрос или повторный.
если перезагрузили страницу и нажимаем перевод еще раз пока не получили ответ по первой операции, это будет новый запрос или повторный?
если надо выполнить подряд два одинаковых перевода(один и тот же получатель и сумма), то не получится ли что пользователю придет два подтверждения, а по факту перевод будет один?
Ключом уникальности, обычно, выступает форма (страница) + timestamp (до нескольких минут).
Если ключ уникальности одинаковый, значит это один и тот же платеж. Если разные - это разные платежи.
Имхо на frontend совсем не стоит полагаться. Имхо стоит рассматривать начало действия не в момент когда клиент "подтверждает перевод", а в момент когда он выбирает опцию - "сделать перевод". Именно в этот момент должен создаваться ключ операции (причем тоже не на стороне клиента) и именно с этим ключом операция и будет "финализироваться" ровно один раз, сколько бы запросов не отправлял клиент на сервер. Это и обеспечит идемпотентность.
Стандарт решения проблемы двойных списаний в финтех, или О чем спросят системного аналитика на собеседовании