在Javascript中使用fetch的相对路径

时间:2016-04-02 04:08:26

标签: javascript path fetch relative-path

我对Javascript中相对路径的体验感到惊讶。我把情况归结为以下几点:

假设您有一个目录结构,如:

2

我的所有app/ | +--app.html +--js/ | +--app.js +--data.json 都会运行app.html

js/app.js

<!DOCTYPE html> <title>app.html</title> <body> <script src=js/app.js></script> </body> 加载JSON文件并将其粘贴在app.js的开头:

body

数据是有效的JSON,只是一个字符串:

// js/app.js
fetch('js/data.json') // <-- this path surprises me
  .then(response => response.json())
  .then(data => app.data = data)

这是"Hello World" 的极小用法,但我感到惊讶的是,我传递给fetch的网址必须相对于fetch,而不是相对于app.html }。我希望这条路径能够正常工作,因为app.jsdata.json位于同一目录(app.js)中:

js/

有没有解释为什么会这样?

4 个答案:

答案 0 :(得分:23)

当您说fetch('data.json')时,您实际上是在请求http://yourdomain.com/data.json,因为它与您提出请求的网页相关。您应该使用正斜杠,这将指示路径相对于域根:fetch('/js/data.json')。或者使用您的域fetch('http://yourdomain.com/js/data.json')完全保持质量。

答案 1 :(得分:2)

这并非完全是建议,因为它依赖于不能保证在任何地方都能工作或在未来继续工作的许多事情,但是它在我需要的地方对我有用,可能会有所帮助你。

const getRunningScript = () => {
    return decodeURI(new Error().stack.match(/([^ \n\(@])*([a-z]*:\/\/\/?)*?[a-z0-9\/\\]*\.js/ig)[0])
}

fetch(getRunningScript() + "/../config.json")
  .then(req => req.json())
  .then(config => {
    // code
  })

答案 2 :(得分:1)

理解为什么必须如此的一种简单方法是考虑如果我们在 app/js/helper/logfetch.js 中编写辅助函数会发生什么:

// app/js/helper/logfetch.js
function logFetch(resource) {
    console.log('Fetching', resource);
    return fetch(resource);
}

现在,考虑一下如果我们使用来自 app/js/app.js 的 logFetch 会发生什么:

// app/js/app.js
fetch('data.json');    // if this is relative to js/, then ...
logFetch('data.json'); // should this be relative to js/ or js/helper/?

我们可能希望这两个调用返回相同的内容 - 但如果 fetch 与包含的文件相关,那么 logFetch 将请求 js/helper/data.json 而不是与 fetch 一致的内容。

如果 fetch 可以感知它是从哪里调用的,那么为了实现诸如 logFetch 之类的帮助程序库,JavaScript 需要一系列新的调用者位置感知功能。

相比之下,相对于 HTML 文件执行提取提供了更多的一致性。

CSS 的工作方式不同,因为它没有方法调用的复杂性:您无法创建“帮助 CSS 模块”来转换其他 CSS 模块,因此相对路径的概念在概念上更加清晰。

答案 3 :(得分:-1)

2021 年更新


ES6

class Path{
    constructor(path){
        this.arr = path.split('/');
    }

    url(){
        return this.arr.join('/');
    }

    concat(){
        return new Path(this.arr.join('/'));
    }

    backward(n){
        for(let ii = 0; ii < n; ii++){
            this.arr.pop();
        }
        return this;
    }

    forward(arr_or_str){
        if(arr_or_str instanceof Array){
            arr_or_str.forEach(st=>{
                this.arr.push(st);
            });
        }else{
            // string
            this.arr.push(arr_or_str);
        }
        return this;
    }
}

/* e.g.
localhost/8888/test/index.js   backward   localhost/8888/test/
localhost/8888/test/  forward('index.js') localhost/8888/test/index.js
localhost/8888/ forward(['db', 'course.json']) localhost/8888/db/course.json
*/

// for example, I want to fetch `db/course.json` in current directory
fetch(new Path(window.location.href).backward(1).forward(["db", "calendar.json"]).url())
    .then(res => {
        console.log(res.json().result);
    });

如果出现the string did not match the expected pattern,参考this SO post