Câu trả lời thực sự là: Bởi vì bạn không thể tin tưởng vào việc trì hoãn.
Về khái niệm, defer và async khác nhau như sau:
async cho phép tập lệnh được tải xuống trong nền mà không bị chặn. Sau đó, thời điểm nó hoàn tất tải xuống, kết xuất sẽ bị chặn và tập lệnh đó thực thi. Kết xuất lại khi kịch bản đã thực thi.
defer thực hiện điều tương tự, ngoại trừ các yêu cầu để đảm bảo rằng các tập lệnh thực thi theo thứ tự chúng được chỉ định trên trang và chúng sẽ được thực thi sau khi tài liệu đã phân tích xong. Vì vậy, một số tập lệnh có thể hoàn tất tải xuống, sau đó ngồi và đợi tập lệnh tải xuống sau nhưng xuất hiện trước chúng.
Thật không may, do thực sự là một cuộc chiến mèo tiêu chuẩn, định nghĩa của defer thay đổi thông số kỹ thuật và thậm chí trong các thông số kỹ thuật gần đây nhất không cung cấp một đảm bảo hữu ích. Như câu trả lời ở đây và vấn đề này chứng minh, các trình duyệt thực hiện trì hoãn khác nhau:
- Trong một số trường hợp nhất định, một số trình duyệt có lỗi khiến
defer
tập lệnh bị lỗi .
- Một số trình duyệt trì hoãn
DOMContentLoaded
sự kiện cho đến khi defer
tập lệnh được tải và một số trình duyệt thì không.
- Một số trình duyệt vâng lời
defer
trên <script>
các yếu tố với mã nội tuyến và không có một src
thuộc tính, và một số bỏ qua nó.
May mắn là thông số kỹ thuật ít nhất chỉ định rằng async ghi đè lên defer. Vì vậy, bạn có thể coi tất cả các tập lệnh là không đồng bộ và nhận được rất nhiều hỗ trợ trình duyệt như vậy:
<script defer async src="..."></script>
98% trình duyệt được sử dụng trên toàn thế giới và 99% ở Hoa Kỳ sẽ tránh bị chặn với phương pháp này.
(Nếu bạn cần đợi cho đến khi tài liệu phân tích xong, hãy lắng nghe sự DOMContentLoaded
kiện hoặc sử dụng .ready()
chức năng tiện dụng của jQuery . Dù sao bạn cũng muốn làm điều này để trở lại duyên dáng trên các trình duyệt hoàn toàn không thực hiện defer
.)