Javascript 如何读取a中的文件<;脚本>;应答器

Javascript 如何读取a中的文件<;脚本>;应答器,javascript,webgl,Javascript,Webgl,很长一段时间以来,我经常在一个问题上伤害自己:我正在运行一个使用着色器代码的WebGL api。这些着色器存储在我的html页面头部的Balise中,如下所示: <script id="vertex-shader" type="x-shader/x-vertex"> [vertex shader code here...] </script> <script id="fragment-shader" type="x-shader/x-fragment"> [f

很长一段时间以来,我经常在一个问题上伤害自己:我正在运行一个使用着色器代码的WebGL api。这些着色器存储在我的html页面头部的Balise中,如下所示:

<script id="vertex-shader" type="x-shader/x-vertex">
[vertex shader code here...]
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
[fragment shader code here...]
</script>

[此处的顶点着色器代码…]
[此处的片段着色器代码…]
但我不喜欢将GLSL代码直接放在html页面中。因此,我想做以下工作:

<script id="vertex-shader" type="x-shader/x-vertex" src="path/to/shader/file.vert"></script>
<script id="fragment-shader" type="x-shader/x-fragment" src="path/to/shader/file.frag"></script>

并为每个着色器提供自己的文件,仅在html脚本应答器中提供其路径

但是,一旦加载页面,如何从javascript代码访问该文件?我知道我必须使用
FileReader
对象来读取它,我知道如何使用它,但我不知道如何到达与着色器的源文件相对应的
文件
对象,即使我获得了字符串中的完整路径

我不想发出Ajax请求,因为我不想在加载页面后在服务器上发出更多请求


请告诉我如何从他的路径打开文件。。。或者如果我在这里试图做的是不可能的。

最简单的事情是向文件发出AJAX GET HTTP请求:

function getShader(id){
   return new Promise(function(resolve, reject){ // return a future
       var script = document.getElementById(id).src;
       var xhr = new XMLHttpRequest;
       xhr.onload = function(){ resolve(xhr.responseText); };
       xhr.onerror = reject;
       xhr.open("GET", script);
       xhr.send(); 
   });
}
这反过来会让你做到:

getShader("vertex-shader").then(function(content){
    // content is the contents of the file.
});
loadAllShaders().then(function(map){
    map["fragment-shader"]; // contains the content of the shader
});
您还可以漫游DOM并将所有着色器放置在地图中,类似地:

function loadAllShaders(){ 
  var shaders = document.querySelectorAll('[type="x-shader/x-vertex"]');
    var futures = [], names = [];
    for(var i = 0; i < shaders.length; i++){
       futures.push(getShader(shaders[i].id));
       names.push(shaders[i].id);
    }

    return Promise.all(shaders).then(function(results){
        var obj = {};
        names.forEach(function(name, i){
           obj[name] = results[i];
        });
        return obj;
    });
}

您不需要使用文件阅读器,只需要ajax。您需要获取src atrib的URL,并在其他脚本查看标记并发现它们为空之前将响应推送到html脚本标记中。我不想使用Ajax,因为我不想在页面完全加载后再向服务器发出任何请求。着色器和其他JavaScript文件一样是一个脚本,有没有任何方法可以像.js文件一样将它们传输到客户端?@Aracthor当您使用的脚本类型不是text/JavaScript时,客户端无论如何都不会向服务器发出请求,因此不会引起额外的请求。不,这不仅仅是一个脚本,就JS而言,这是一个语法错误,只有有效的JS才能被外部链接。真正的外部标记和ajax都会发出http请求,因此使用ajax不会节省任何东西或增加任何负担。您确定不发送额外的http请求就无法获取文件吗?我可能有许多着色器在一个页面上使用,所以我可以提出几十年的要求像这样。。。它看起来很重。@Aracthor当你有一个
script
标记时,即使是JS脚本,浏览器也会通过HTTP请求来获取它-当你有一个脚本标记,它的特定类型不是text/javascript时,浏览器不会自己发出请求-所以你会这样做。这个答案中的这种方法提出了尽可能多的要求,而不是更多。在生产环境中,您应该建立一个具有缩小和连接功能的构建(例如gulp),这样它就只需要发出一个HTTP请求。没有请求,如何获取远程文件?这不是JS问题,而是物理问题。避免这些“额外”请求的最简单方法是简单地将内容内联,就像最初交付的一样。