Если у меня есть такой тег сценария:
<script
id = "myscript"
src = "http://www.example.com/script.js"
type = "text/javascript">
</script>
Я хочу получить содержимое файла "script.js". Я думаю о чем-то вроде document.getElementById("myscript").text, но в данном случае он не работает.
Где бы вы его кэшировали? Я имею в виду, как бы вы могли сохранить ваши кэшированные данные по истечении срока действия скрипта, загруженного на страницу?
Маркус: Я рекомендую добавить пояснение к вашему запросу, иначе вы просто продолжите получать ответы в том же духе, что и ниже :)
Вызывая функцию javascript, которая сохраняет для меня это значение. Но на самом деле это не входит в рамки этого вопроса.
Этому вопросу несколько лет. Тем не менее, я просто хотел бы выложить свои 2 цента относительно современного использования этого. Растет тенденция к использованию клиентских шаблонов, и, как правило, способ определения шаблонов вне javascript - это встраивание шаблонов в тег <script> (John Resig Microtemplating), чтобы избежать экранирования. Однако это означает, что шаблоны не кэшируются, и они должны отображаться вместе с побочным контентом. Обходной путь может заключаться в том, чтобы поместить шаблоны в отдельный файл и использовать тег «скрипт» для ссылки на него, но вы не можете получить содержимое файла без AJAX.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы хотите получить содержимое файла http://www.example.com/script.js? Если это так, вы можете обратиться к методам AJAX для получения его содержимого, предполагая, что он находится на том же сервере, что и сама страница.
Не могли бы вы подробнее рассказать о том, чего пытаетесь достичь?
Я хочу сохранить содержимое сценария, чтобы я мог кэшировать его и использовать напрямую через некоторое время без необходимости извлекать его с внешнего веб-сервера (не на том же сервере, что и страница).
Если это так, не беспокойтесь об этом, браузер сам обрабатывает кеширование внешних JS-скриптов.
@Gizmo, тогда почему Google кеширует скрипты в локальном хранилище? Кеширование браузера ненадежно.
Кэширование в браузере @Qix надежно, но часто требует обращения к серверу и обратно (например, для проверки ETag). Использование локального хранилища может предотвратить это возвращение.
Не знаете, зачем вам это нужно?
Другой способ - разместить скрипт где-нибудь в скрытом элементе и использовать Eval для его запуска. Затем вы можете запросить свойство innerHtml объекта.
если вам нужно содержимое атрибута src, вам нужно будет выполнить запрос ajax и посмотреть текст ответа. Если у вас есть js между ними, и вы можете получить к нему доступ через innerHTML.
Это может быть интересно: http://ejohn.org/blog/degrading-script-tags/
Если вы хотите получить доступ к атрибутам тега <script>, а не к содержимому script.js, то XPath вполне может быть тем, что вам нужно.
Это позволит вам получить каждый из атрибутов скрипта.
Если вам нужно содержимое файла example.js, вы можете запустить AJAX-запрос, чтобы получить его.
Если указан атрибут src, пользовательские агенты - требуется, чтобы игнорировать содержимое элемента, если вам нужно получить к нему доступ из внешнего скрипта, то вы, вероятно, делаете что-то не так.
Обновление: я вижу, вы добавили комментарий к эффекту, что хотите кэшировать скрипт и использовать его позже. С какой целью? Предполагая, что ваш HTTP дружелюбен к кешу, ваши потребности в кешировании, вероятно, уже позаботятся браузером.
Вот такой сценарий. Страница добавляет контент с помощью jsonp. Я хочу, чтобы расширение использовало этот контент для добавления дополнительной информации. Теперь я могу отслеживать события добавления jsonp, когда я слежу за DOMSubtreeModified, но не могу получить доступ к источнику (который содержит только вызов функции с некоторым json).
@AndriusBentkus - Если у вас есть новый вопрос, задать новый вопрос.
У меня точно такой же вопрос, я только что привел вам сценарий, в котором его вопрос имеет смысл.
.text действительно получил содержимое тега, просто у вас нет ничего между вашим открытым тегом и вашим конечным тегом. Вы можете получить атрибут src элемента, используя .src, а затем, если вы хотите получить файл javascript, вы должны перейти по ссылке и сделать для него запрос ajax.
Я не думаю, что содержимое будет доступно через DOM. Вы можете получить значение атрибута src и использовать AJAX для запроса файла с сервера.
В комментарии к моему предыдущему ответу:
I want to store the content of the script so that I can cache it and use it directly some time later without having to fetch it from the external web server (not on the same server as the page)
В этом случае вам лучше использовать сценарий на стороне сервера для извлечения и кеширования файла сценария. В зависимости от настроек вашего сервера вы можете просто получить файл (периодически через cron, если вы ожидаете, что он изменится) или сделать что-то подобное с небольшим скриптом на любом языке по вашему выбору.
Используя привязку DOM в стиле 2008 года, это было бы лучше:
document.getElementById('myscript').getAttribute("src");
document.getElementById('myscript').getAttribute("type");
Это не имеет ничего общего с вопросом
Вы хотите использовать свойство innerHTML для получения содержимого тега скрипта:
document.getElementById("myscript").innerHTML
Но, как сказал @olle в другом ответе, вы, вероятно, захотите прочитать: http://ejohn.org/blog/degrading-script-tags/
Я бы посоветовал ответить на этот вопрос с помощью свойства "innerHTML" элемента DOM. Конечно, если сценарий загружен, вы делаете нет, нужно сделать вызов Ajax, чтобы получить его.
Итак, Sugendran должен быть правильным (не уверен, почему он был отклонен без объяснения причин).
var scriptContent = document.getElementById("myscript").innerHTML;
Свойство innerHTML элемента сценария должно предоставить вам содержимое сценария в виде строки при условии, что элемент сценария:
олле также дает ответ, но я думаю, что он «запутался», когда он предложил сначала загрузить его через ajax, и я думаю, что он имел в виду «встроенный», а не промежуточный.
if you where to have the js between and you could access it through innerHTML.
Относительно полезности этой техники:
Я попытался использовать этот метод для регистрации ошибок на стороне клиента (исключений javascript) после получения «неопределенных переменных», которые не содержатся в моих собственных сценариях (например, плохо внедренные сценарии с панелей инструментов или расширений), поэтому я не Думаю, это выход из положения.
Пробовал в Firefox v.24 - не работает с внешними скриптами.
Это не работает - вы получаете содержимое самого тега сценария, а не содержимое внешнего сценария.
Обновлять: HTML-импорт теперь устарел (альтернативы).
Я знаю, что уже немного поздно, но некоторые браузеры поддерживают свойство tag LINK rel = "import".
http://www.html5rocks.com/en/tutorials/webcomponents/imports/
<link rel = "import" href = "/path/to/imports/stuff.html">
В остальном Ajax по-прежнему является предпочтительным способом.
Я искал это решение отчасти потому, что я не использую веб-сервер для обслуживания страниц (я получаю его локально прямо из файловой системы), и я думаю, что вы не можете использовать xmlhttprequest без веб-сервера.
@Jose_X: вы можете использовать флаги браузера, чтобы обойти это ограничение. Я думаю, что для Chrome это что-то вроде "--allow-file-access-from-files" при запуске браузера. Может быть chrome: // flags (onextrapixel.com/2014/09/01/…)
Этот интерфейс устарел.
да, Ajax - это способ сделать это, как в принятом ответе. Если вдаваться в подробности, то здесь много подводных камней. Если вы используете jQuery.load(...), предполагается неправильный тип содержимого (html вместо application / javascript), что может испортить ситуацию, поместив нежелательный <br> в ваш (scriptNode) .innerText и тому подобное. Затем, если вы используете jQuery.getScript(...), загруженный сценарий немедленно запускается, что может быть не тем, что вам нужно (может испортить порядок, в котором вы хотите загружать файлы, если у вас их несколько).
Я счел лучше использовать jQuery.ajax с dataType: "text"
Я использовал эту технику Ajax в проекте с набором фреймов, где для набора фреймов и / или нескольких фреймов требуется один и тот же JavaScript, чтобы сервер не отправлял этот JavaScript несколько раз.
Вот код, протестированный и работающий:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<script id = "scriptData">
var scriptData = [
{ name: "foo" , url: "path/to/foo" },
{ name: "bar" , url: "path/to/bar" }
];
</script>
<script id = "scriptLoader">
var LOADER = {
loadedCount: 0,
toBeLoadedCount: 0,
load_jQuery: function (){
var jqNode = document.createElement("script");
jqNode.setAttribute("src", "/path/to/jquery");
jqNode.setAttribute("onload", "LOADER.loadScripts();");
jqNode.setAttribute("id", "jquery");
document.head.appendChild(jqNode);
},
loadScripts: function (){
var scriptDataLookup = this.scriptDataLookup = {};
var scriptNodes = this.scriptNodes = {};
var scriptNodesArr = this.scriptNodesArr = [];
for (var j=0; j<scriptData.length; j++){
var theEntry = scriptData[j];
scriptDataLookup[theEntry.name] = theEntry;
}
//console.info(JSON.stringify(scriptDataLookup, null, 4));
for (var i=0; i<scriptData.length; i++){
var entry = scriptData[i];
var name = entry.name;
var theURL = entry.url;
this.toBeLoadedCount++;
var node = document.createElement("script");
node.setAttribute("id", name);
scriptNodes[name] = node;
scriptNodesArr.push(node);
jQuery.ajax({
method : "GET",
url : theURL,
dataType : "text"
}).done(this.makeHandler(name, node)).fail(this.makeFailHandler(name, node));
}
},
makeFailHandler: function(name, node){
var THIS = this;
return function(xhr, errorName, errorMessage){
console.info(name, "FAIL");
console.info(xhr);
console.info(errorName);
console.info(errorMessage);
debugger;
}
},
makeHandler: function(name, node){
var THIS = this;
return function (fileContents, status, xhr){
THIS.loadedCount++;
//console.info("loaded", name, "content length", fileContents.length, "status", status);
//console.info("loaded:", THIS.loadedCount, "/", THIS.toBeLoadedCount);
THIS.scriptDataLookup[name].fileContents = fileContents;
if (THIS.loadedCount >= THIS.toBeLoadedCount){
THIS.allScriptsLoaded();
}
}
},
allScriptsLoaded: function(){
for (var i=0; i<this.scriptNodesArr.length; i++){
var scriptNode = this.scriptNodesArr[i];
var name = scriptNode.id;
var data = this.scriptDataLookup[name];
var fileContents = data.fileContents;
var textNode = document.createTextNode(fileContents);
scriptNode.appendChild(textNode);
document.head.appendChild(scriptNode); // execution is here
//console.info(scriptNode);
}
// call code to make the frames here
}
};
</script>
</head>
<frameset rows = "200pixels,*" onload = "LOADER.load_jQuery();">
<frame src = "about:blank"></frame>
<frame src = "about:blank"></frame>
</frameset>
</html>
Теги сценария tl; dr не подчиняются CORS и политика того же происхождения, и поэтому javascript / DOM не может предлагать доступ к текстовому содержимому ресурса, загруженного через тег <script>, иначе это нарушит same-origin-policy.
длинная версия:
Большинство других ответов (и принятый ответ) правильно указывают, что способ «правильный» для получения текстового содержимого файла javascript, вставленного через <script>, загруженного на страницу, использует XMLHttpRequest для выполнения другого отдельного дополнительного запроса ресурса. указано в свойстве сценария src, что продемонстрирует короткий код javascript ниже. Однако я обнаружил, что в других ответах не рассматривается вопрос, почему нужно получить текстовое содержимое файлов javascript, а именно то, что разрешение доступа к содержимому файла, включенного через <script src=[url]></script>, нарушит политики CORS, например современные браузеры предотвращают XHR ресурсов, которые не предоставляют заголовок Доступ-Контроль-Разрешить-Происхождение, следовательно, браузеры не позволяют получить контент никаким другим способом, кроме тех, которые подпадают под CORS.
С помощью следующего кода (как упоминалось в других вопросах «используйте XHR / AJAX») можно сделать еще один запрос для всех не встроенных тегов сценария в документе.
function printScriptTextContent(script)
{
var xhr = new XMLHttpRequest();
xhr.open("GET",script.src)
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.info("the script text content is",xhr.responseText);
}
};
xhr.send();
}
Array.prototype.slice.call(document.querySelectorAll("script[src]")).forEach(printScriptTextContent);
и поэтому я не буду повторять это, но вместо этого хотел бы добавить через этот ответ аспект, почему это
Спасибо - это единственный ответ, который объясняет, что Почему вы используете должен AJAX для получения текста в обратном направлении на сервер, и почему то, что уже было загружено тегом сценария, иначе недоступно.
Забавно, но мы не можем, мы должны снова загрузить их через Интернет.
Скорее всего, браузер прочитает его кеш, но все равно отправляется эхо-запрос для проверки длины содержимого.
[...document.scripts].forEach((script) => {
fetch(script.src)
.then((response) => response.text() )
.then((source) => console.info(source) )
})
Мне сложно понять, зачем вам нужен доступ к контенту? Не могли бы вы дать некоторую информацию о том, что вы планируете с ним делать?