#javascript #asynchronous #onload #document.write
#javascript #асинхронный #onload #document.write
Вопрос:
Я пытаюсь загрузить определенный скрипт после выполнения загрузки страницы, что-то вроде этого:
function downloadJSAtOnload(){
var element = document.createElement("script");
element.src = "scriptSrc";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
И хотя этот скрипт, похоже, выполняет и загружает ‘ScriptSrc’ и добавляет его прямо перед концом тега body, он выдает следующее сообщение (не ошибку) в консоли (chrome)
Не удалось выполнить «запись» в «Документе»: невозможно выполнить запись в документ из асинхронно загруженного внешнего скрипта, если он явно не открыт.
Что это вообще значит? И должен ли я сделать что-то по-другому? Даже если я получаю ожидаемое поведение?
Комментарии:
1. Это означает, что загружаемый вами скрипт выполняется
document.write
, что не поддерживается при добавлении его на страницу через<script>
тег. Вероятно, вам следует посмотреть, что делает скрипт, и изменить сценарий, чтобы он не использовалсяdocument.write
.2. понял, но я не могу изменить этот скрипт. Назовите это бюрократией. Могу ли я заставить скрипт загружаться синхронно? Нет права, потому что это происходит после загрузки страницы.
3. Да, вы можете загружать содержимое скрипта синхронно с AJAX, а затем
eval
с ним, хотя я не уверен на 100%, сработает ли это.4. недавно нашел фантастическую библиотеку на github, которая прекрасно обходит это «ограничение»: github.com/krux/postscribe
5. @universio Я также сталкиваюсь с такой же проблемой.
document.write('x3Cscript type="text/javascript" src="http://ads.appnexus.com/ttj?id=xyzpqramp;cb=${CACHEBUSTER}">x3C/script>');
это работает отлично, но когда я создаю скрипт с помощью createElement(‘script’) Я сталкиваюсь с той же проблемой. Можете ли вы предложить что-нибудь здесь?
Ответ №1:
Асинхронно загруженный скрипт, скорее всего, будет запущен ПОСЛЕ того, как документ будет полностью проанализирован и закрыт. Таким образом, вы не можете использовать document.write()
из такого скрипта (ну, технически вы можете, но он не будет делать то, что вы хотите).
Вам нужно будет заменить любые document.write()
операторы в этом скрипте явными манипуляциями с DOM, создав элементы DOM, а затем вставив их в конкретный родительский элемент с .appendChild()
.insertBefore()
помощью параметра или или .innerHTML
или какого-либо механизма для прямого манипулирования DOM, подобного этому.
Например, вместо этого типа кода во встроенном скрипте:
<div id="container">
<script>
document.write('<span style="color:red;">Hello</span>');
</script>
</div>
Вы могли бы использовать это для замены встроенного скрипта выше в динамически загружаемом скрипте:
var container = document.getElementById("container");
var content = document.createElement("span");
content.style.color = "red";
content.innerHTML = "Hello";
container.appendChild(content);
Или, если в контейнере не было другого содержимого, к которому вам нужно было просто добавить, вы могли бы просто сделать это:
var container = document.getElementById("container");
container.innerHTML = '<span style="color:red;">Hello</span>';
Комментарии:
1. Но разве я не делаю что-то подобное, когда указываю «document.body.appendChild(элемент)»?
2. @jfriend, повторите » но он не будет делать то, что вы хотите «, что, если это произойдет? Как мне включить его, если я этого хочу? (Раньше это работало в старых браузерах.)
3. @Pacerier — использование
document.write()
после завершения загрузки документа приводит к очистке текущего документа, а затем запись переходит в новый пустой документ. Если вы хотите такого поведения, просто очистите текущий DOM перед вставкой вашего содержимого. Если у вас есть более подробный вопрос, чем этот, пожалуйста, задайте новый вопрос, покажите код, который у вас есть, и опишите желаемый результат.
Ответ №2:
Немного поздно для вечеринки, но Krux создал для этого скрипт под названием Postscribe . Мы смогли использовать это, чтобы обойти эту проблему.
Комментарии:
1. каков наилучший способ передать эту библиотеку с помощью нашей библиотеки JavaScript? Ситуация такова, что мы даем теги JS клиенту, который запускается на этом веб-сайте.
2. Я не уверен на 100%, о чем вы спрашиваете здесь @RockStar, но любые обычные способы включения JS должны работать. Можно подтянуть cdnjs.com/libraries/postscribe и копировать/вставить код в существующий файл JS, или вы могли бы просто добавить <script> tag pointing to the cdnjs-hosted version of the file. Возможно, вам понадобится, чтобы он загружался перед другими скриптами, поэтому, если у вас возникли проблемы с его работой, это может быть возможной причиной.
3. Мы предоставили владельцу веб-сайта ссылку JavaScript CDN для размещения рекламы с использованием этого тега. Мы не можем попросить каждого владельца разместить это postscribe.js поэтому нам нужно предоставить его с помощью нашего JS.
4. postscribe, похоже, вообще ничего не делает, если вы явно не используете
postscribe
функцию — очень разочаровывает5. @RockStar Какое решение вы получили для своей проблемы. Даже у меня такая же проблема
Ответ №3:
В случае, если это кому-то полезно, у меня была такая же проблема. Я вводил нижний колонтитул на веб-страницу с помощью jQuery. Внутри этого нижнего колонтитула были некоторые скрипты Google для рекламы и переназначения. Мне пришлось переместить эти скрипты из нижнего колонтитула и поместить их непосредственно на страницу, и это устранило уведомление.
Комментарии:
1. У меня была такая же проблема, но скрипт находился внутри пакета, созданного менеджером тегов. Проблема была вызвана
async
атрибутом, и единственным решением было удалить этот атрибут, поскольку мне не разрешено перемещать скрипты из нашего менеджера тегов.
Ответ №4:
Вы также можете вызвать
document.open() before document.write()
вызовите
document.close()
когда вы закончите.
Возможно, это не лучшая практика для реальной веб-страницы, Но для тестирования и т. Д. Можно использовать.