Использование сценария async / defer / onload в примерах JavaScript API Google

1

В различных образцах javascript, которые Google предоставляет для своего API (например, здесь), они используют следующий код для загрузки скрипта из html:

<script async defer src="https://apis.google.com/js/api.js" 
    onload="this.onload=function(){};handleClientLoad()" 
    onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

Я понимаю, что async/defer сообщает браузеру, когда загружать и исполнять скрипт и несколько противоречить друг другу. У меня мало вопросов:

  1. В чем смысл использования async и defer в этом контексте?
  2. Почему Google решил использовать эту технику? Имеет ли он какие-либо результаты или другие преимущества?
  3. В событии onload, почему они сначала назначают пустую функцию (function(){};) событию перед вызовом handleClientLoad()?
  4. Если я хочу переместить весь javascript в отдельный файл js, какой лучший подход для загрузки обоих скриптов? Поскольку новый js файл будет зависеть от api.js и не может быть загружен асинхронно?

Благодарю.

Теги:
google-api

1 ответ

1
Лучший ответ

Это довольно хорошо освещено в стандарте WHAT-WG для HTML-раздела, посвященного async и defer, который включает эту удобную графику:

Изображение 174551

1. В чем смысл использования async и отсрочки в этом контексте?

Если браузер поддерживает async, он игнорирует defer и работает async. Если нет, но он поддерживает defer, вместо этого происходит отсрочка. Если это не поддерживает, скрипт блокирует разбор DOM, но все современные браузеры поддерживают хотя бы один.

2. Почему Google решил использовать эту технику? Имеет ли он какие-либо результаты или другие преимущества?

async извлекает сценарий, не блокируя разбор и рендеринг DOM, и запускает его, как только он доступен, даже если разбор и рендеринг DOM все еще продолжается. defer также избегает блокировки разбора и рендеринга DOM, но не запускает скрипт до тех пор, пока синтаксический анализ не будет завершен (например, потенциально позже).

3. В событии onload, почему они сначала назначают пустую функцию (function(){};) событию перед вызовом handleClientLoad()?

Это становится ясно, если посмотреть на onreadystatechanged: В основном это гарантирует, что handleClientLoad вызывается только один раз GAPI, потенциально не дважды (один раз onload и один раз onreadystatechanged.)

4. Если я хочу переместить весь javascript в отдельный файл js, какой лучший подход для загрузки обоих скриптов? Поскольку новый js файл будет зависеть от api.js и не может быть загружен асинхронно?

Ну, он может быть загружен асинхронно, вам просто нужно обработать условие гонки с помощью api.js Я бы наверное:

  1. Имеет handleClientLoad в встроенном скрипте над тегом script загружающим api.js, примерно так:

    var clientLoaded = false;
    function handleClientLoad() {
        if (!clientLoaded &&
            typeof mainScriptLoad !== "undefined" &&
            typeof gapi !== "undefined") {
            clientLoaded = true;
            mainScriptLoad();
        }
    }
    
  2. Имейте mainScriptLoad в отдельный файл.

  3. В конце вашего отдельного файла вызовите handleClientLoad.

Сюда:

  • Если ваш скрипт работает первым, он вызовет handleClientLoad но handleClientLoad увидит, что GAPI еще не загружен и ничего не сделает; позже, когда GAPI загрузится, он вызовет handleClientLoad и вызовет mainScriptLoad потому что все готово.
  • Если ваш скрипт запускается после загрузки GAPI, он вызовет handleClientLoad но handleClientLoad увидит, что ваш основной скрипт еще не загружен и не пытается его вызвать. Позже, когда ваш скрипт загружается и вызывает handleClientLoad, handleClientLoad вызовет mainScriptLoad потому что все готово.
  • 1
    Отличный ответ. Теперь понятно. Спасибо.
  • 0
    Последний вопрос - зачем нужны onload и onreadystatechange ? Для поддержки разных браузеров?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню