El siguiente fragmento se toma de un ejemplo en el documento de la API de Google . La parte intrigante de este fragmento es que el onload
de eventos de carga en los dos <script async>
en <head>
se definen más adelante en <body>
. ¿El evento de onload
en el script asíncrono solo se activa después de analizar el <body>
? ¿Alguna especificación proporciona tal garantía? ¿O este código solo es correcto bajo la suposición implícita de que estos dos scripts particulares en <head>
tardan mucho tiempo en recuperarse y ejecutarse?
<!DOCTYPE html> <html> <head> <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script> <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script> </head> <body> <script> function gapiLoad() { // do something } function gisInit() { // do something } // there are other stuffs... </script> </body> </html>
Onload EventHandler Admite estas etiquetas HTML: <body>, <frame> (deprecated), <iframe>, <img>, <input type="image">, <link>, <script>, <style>, <track>, <svg>, <use>, <foreignObject>, <image>, <object>, <embed
. (Gracias a @Kaiido por completar esta lista).
Si quiere estar seguro de que su JS solo se ejecuta cuando se carga el DOM, puede cargar una función de controlador desde la etiqueta del cuerpo.
Nota : al usar onload con async, debe saber que cuando los scripts se cargan de forma asíncrona, retrasan el evento onload. A menudo, los scripts cargados de forma asíncrona cargan otros scripts.
function start() { gapiLoad(); gisInit(); } function gapiLoad() { console.log(1) // do something } function gisInit() { console.log(2) // do something } // there are other stuffs...
<head> <script async defer src="https://apis.google.com/js/api.js" ></script> <script async defer src="https://accounts.google.com/gsi/client"></script> </head> <body onload="start()">
No async
no garantiza que el script se ejecutará después de que se haya analizado el documento. Cargará el script en paralelo y lo ejecutará tan pronto como sea posible , por lo que si la recuperación del script finaliza antes de que el analizador llegue al <script>
donde se están definiendo las devoluciones de llamada, eso sí sería un problema:
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script> <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script> <!-- This one is blocking for at least 3s --> <script src="https://deelay.me/3000/https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script> function gapiLoad() { console.log("loaded"); } function gisInit() { console.log("init"); } </script>
defer
hace eso, pero si tanto defer
como async
están configurados, el comportamiento de async
gana, por lo que debemos asegurarnos de que solo defer
esté configurado.
<script defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script> <script defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script> <!-- this one is blocking for at least 3s --> <script src="https://deelay.me/3000/https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script> function gapiLoad() { console.log("loaded"); } function gisInit() { console.log("init"); } </script>