JavaScript изменил ID заказа. И даже не извинился 😬

Представьте, что бэкенд вернул корректный идентификатор заказа. Фронтенд получил JSON, успешно его распарсил, никаких исключений. Только номер заказа почему-то изменился.

Проверим на простом примере.

const order = JSON.parse(’{“id”:9007199254740993}’);

console.log(order.id); // 9007199254740992

Отправили 9007199254740993, получили 9007199254740992. Потеряли единицу, зато без единой ошибки :)

Причина в том, что обычный Number в JavaScript использует формат IEEE 754 с ограниченной точностью. Максимальное безопасное целое число равно 9007199254740991.

Когда JSON.parse преобразует большое целое число в Number, точность может потеряться ещё на этапе разбора.

И нет, BigInt(order.id) уже не спасёт. Он честно преобразует неправильное число в большое неправильное число.

Что делать?

Если идентификаторы могут превышать безопасный диапазон, передавайте их строками. Например, {“id”:“9007199254740993”}.

А если формат ответа изменить нельзя, в современных реализациях JavaScript можно использовать третий аргумент reviver-функции JSON.parse и читать исходное представление числа через context.source. Но поддержку этой возможности в целевой среде нужно проверить.

И вот вам ситуация, когда приложение работает, запросы успешные, ошибок в консоли нет, а данные уже повреждены.

Иногда JavaScript даже не нужно падать, чтобы сломать бизнес-логику.

JavaScript изменил ID заказа. И даже не извинился 😬 | Сетка — социальная сеть от hh.ru