The best sellers page
had one job.
Most popular first.
The server did the sorting.
It ran the query,
ordered by units sold,
and sent the result
as an object keyed by product id.
{"1042": {...}, "87": {...}, "530": {...}}
Easy lookups on the page,
the developer said.
The page looped over Object.values
and drew the cards.
The cards came out
87, 530, 1042.
Not by sales.
By id.
The oldest products
sat at the top of the best sellers,
whether anyone bought them or not.
Nobody noticed for a month,
because the oldest products
were also some of the best sellers.
Then a new range launched,
outsold everything,
and appeared at the bottom.
The server was right.
You can see it in the response.
The order is there,
on the wire,
exactly as sorted.
The page threw it away.
JavaScript objects
do keep keys in the order you add them.
Almost.
The rule in the language specification
has a first step
that most people never read.
Keys that look like array indexes,
whole numbers written plainly,
always come first,
in ascending numeric order.
Only then
do the other string keys follow,
in the order they were created.
JSON.parse created the keys
in the server's order.
Object.values
handed them back
in the language's order.
"87" is an index.
"sku-87" is not,
and would have kept its place.
"087" is not either.
So the same code
sorts some catalogues
and not others,
depending on what your ids look like.
The fix is not a cleverer key.
An object is a lookup.
It was never a promise
about sequence.
If the order matters,
send a list.
[{"id": 1042, ...}, {"id": 87, ...}]
An array keeps its order
because order is what an array is.
If you also need fast lookups,
build a Map from the list on the page.
A Map keeps insertion order
for every key,
numbers included.
And test the order
with ids that would sort differently
from the answer you expect.
A test where popularity
and id happen to agree
passes for the wrong reason.
Any time a format
carries both a lookup and an order,
ask which of the two
it actually promises.
The other one
is a coincidence
waiting for a new product.
– Serguey Asael Shinder
Top comments (0)