Dans sa chronique CodeSOD, Remy Porter raconte comment Karen, développeuse chargée de maintenir des tests de spécification TypeScript, a traqué une instabilité rare mais persistante. Les tests fonctionnels basés sur les spécifications échouaient environ trois à quatre fois par millier d'exécutions, tandis que les tests unitaires restaient verts. Les opérations étaient sensibles au temps, et les tests utilisaient déjà des fenêtres temporelles généreuses, donc la source de l'instabilité n'était pas évidente.
À plusieurs endroits, les tests devaient attendre au moins deux millisecondes. La fonction utilitaire d'origine était le one-liner idiomatique :
```typescript export const wait = (ms:number) => new Promise((complete) => setTimeout(complete, ms)); ```
La documentation JavaScript standard avertit que `setTimeout` peut attendre plus longtemps que le délai demandé, ce que Karen acceptait. Cependant, la documentation Node.js ne garantit rien sur le moment où le callback est invoqué, ce qui signifie que le timer peut se déclencher avant que le délai ne soit écoulé.
Après de nombreuses heures de débogage, Karen a découvert que ces déclenchements anticipés causaient effectivement les échecs. Elle a remplacé la fonction simple par cette version en polling :
```typescript export const wait = (ms: number) { const target = performance.now() + ms; return new Promise((complete) => { const checkReady = () => { if (performance.now() > target) { complete(); } else { setTimeout(checkReady, 1); } } setTimeout(checkReady, 1); }); } ```
Celle-ci interroge l'heure toutes les millisecondes et ne résout la promesse que lorsque le temps cible est réellement atteint. La modification stabilise les tests, mais l'auteur note que cette solution de contournement est regrettable : elle n'existe que parce que Node.js enfreint la garantie d'ordonnancement que les autres runtimes respectent généralement — attendre au moins aussi longtemps que demandé, même si cela peut être beaucoup plus long.