location.href 는 암묵적 await 가 아니다 — setter 는 동기, navigation 은 태스크

location.href에 값을 넣으면 그 줄에서 바로 페이지가 이동할 것 같다. 마치 **암묵적 await**처럼 거기서 멈춘다고 생각하기 쉽다. 그럼 뒤에 오는 코드는 실행되지 않을까.

location.href = 'https://google.com'
console.log('실행됨 1')
location.href = 'https://google2.com'
console.log('실행됨 2')

둘 다 출력된다. 그리고 이동은 google2.com으로 간다.

await였다면 첫 줄에서 멈춰 실행됨 1도 출력되지 않고 google.com으로 갔어야 한다. 두 결과가 모두 어긋나니 가설은 틀렸다.

실제로는 이렇다. setter는 동기적으로 정상 실행되고 흐름을 끊지 않는다. 문서를 언로드하고 네트워크 요청을 보내는 실제 작업은 태스크로 넘어가 지금 실행 중인 코드가 끝난 뒤에 시작된다. 그리고 두 번째 navigation이 시작되면 진행 중이던 첫 번째가 버려진다1 — 마지막 값이 이기는 건 덮어써서가 아니라 앞의 것이 취소되기 때문이다.

location.href setter가 실행되는 시점과 실제 navigation이 처리되는 시점이 분리되는 이벤트 루프 타임라인

Footnotes

  1. “Set the ongoing navigation for navigable to navigationId. This will have the effect of aborting other ongoing navigations of navigable, since at certain points during navigation changes to the ongoing navigation will cause further work to be abandoned.” — 그리고 문서 언로드·페치는 in parallel 로 넘어간다. (HTML Standard — navigate)

#569raw