Обмен сообщениями в приложении Chrome и ‘loadstop’ по сравнению с синхронизацией .load()

#javascript #webview #google-chrome-app

#javascript #webview #google-chrome-app

Вопрос:

Я разрабатываю приложение Chrome с веб-просмотром. Страницы, предназначенные для веб-просмотров, также могут запускаться в обычном браузере. Если внутри webview страницы отправляют сообщения в главное приложение, но, по-видимому, им сначала нужно получить сообщение из приложения, чтобы знать, куда отправлять свои сообщения.

Нет проблем — основное приложение отправляет сообщение, как только оно видит событие «loadstop», которое сообщает страницам, куда отправлять сообщения. Если страницы нет в webview, она никогда не получит сообщение.

Проблема в том, что мне нужно знать, когда страница должна перестать ждать сообщения, и предположить, что его НЕТ в webview.

Когда происходит ‘loadstop’ относительно событий на странице, таких как jQuery .ready или .load? Есть ли способ перехватить или запустить событие, которое гарантированно произойдет после того, как «loadstop» МОЖЕТ быть замечен в главном приложении и сообщении, отправленном и полученном JavaScript webview.

Ответ №1:

Когда происходит ‘loadstop’ относительно событий на странице, таких как jQuery .ready или .load?

Согласно документации для события loadstop:

Запускается, когда все загрузки на уровне фрейма на гостевой странице (включая все ее подкадры) завершены. Это включает навигацию в текущем документе, а также загрузку на уровне документа подкадра, но не включает асинхронную загрузку ресурсов.

Это наводит на мысль, что это больше похоже на .ready() от jQuery, который выполняется после загрузки дерева DOM, но до ожидания загрузки ресурсов (.css, .js).

Следите за этой страницей документации; она уже значительно улучшилась с тех пор, как две недели назад.


Есть ли способ перехватить или запустить событие, которое гарантированно произойдет после того, как «loadstop» МОЖЕТ быть замечен в главном приложении и сообщении, отправленном и полученном JavaScript webview?

Ваш manifest.json объявляет ваш my-app-main.js фоновый скрипт (и ваше разрешение webview), который запускает ваш my-webview-wrapper.html который включает ваш <webview> тег, а также вставляет некоторый javascript (или источники my-webview-wrapper.js файл), который назначает прослушиватели событий вашему webview с помощью onload функции как таковой:

 onload = function() {
  webview = document.getElementById("the-id-attribute-of-my-webview");
  webview.addEventListener("<EVENT>", function() {
    // the cool stuff you want to do
  }
}
  

<EVENT> может быть любым из событий webview DOM, перечисленных в документации, на которую я ссылался (включая loadstop ). Ваше основное приложение не должно действительно волновать, что все это происходит. (Это асинхронно! Это javascript! Это волшебно!)

Если вы все еще в замешательстве, просто просмотрите образец веб-просмотра Google на GitHub.

Комментарии:

1. Я не уверен, где размещен этот код загрузки — в webview? Таким образом, webview может получать ‘loadstop’ одновременно с основным приложением? Это может быть удобно, но главное приложение абсолютно не волнует. Я предварительно загружаю несколько объявлений (страниц в webviews) для отображения в киоске — им нужны не только изображения, JavaScript …, но им нужно сообщить основному приложению, когда они будут полностью готовы, включая определение их собственной продолжительности воспроизведения. Только тогда главному приложению разрешено планировать их для отображения пользователям, иначе мои клиенты недовольны.

2. Да, код onload помещается на ту же HTML-страницу embedder (или связан с ней), которая вызывает webview. Для вашей конкретной проблемы не могли бы вы просто сделать webview скрытым по умолчанию с помощью CSS, а затем переключить его на отображение из функции обратного вызова loadstop?

3. По сути, это то, что я делаю, но, судя по вашим комментариям и документации, событие loadstop происходит слишком рано для webview — до загрузки асинхронных ресурсов и до того, как JavaScript WebView сможет выполнить свою задачу. Только webview знает, когда это произойдет, поэтому ему нужно отправить сообщение, установить флаг или что-то сделать, а не основное приложение. Кстати, чтобы обойти это, я решил, что основное приложение будет опрашивать веб-просмотры каждую секунду — не асинхронным способом JavaScript, а всего несколькими строками кода в конце.

4. После быстрого просмотра моего кода, в частности, JavaScript на странице webview вызывает window.addEventListener(‘message’, …); поэтому он может слышать основное приложение. Но будет ли это достаточно рано, чтобы превзойти «loadstop», или есть вероятность, что реакция основного приложения на это будет потеряна в киберпространстве? Я боюсь ошибки в состоянии гонки.

5. О, это классное решение. Я недостаточно разбираюсь в Javascript, чтобы сказать, является ли это условием гонки, но кажется , что это так. Вероятно, стоит задать еще один вопрос, чтобы задать этот.