Javascript中具有fetch的相对路径

Relative paths with fetch in Javascript

本文关键字:相对 路径 fetch Javascript      更新时间:2023-11-03

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

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

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>

app.js加载JSON文件并将其粘贴在body:的开头

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

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

"Hello World"

这是fetch的一个非常小的用法,但我很惊讶,我传递给fetch的URL必须相对于app.html,而不是相对于app.js。我希望这个路径能工作,因为data.jsonapp.js在同一目录(js/)中:

fetch('data.json') // nope

为什么会出现这种情况,有什么解释吗?

当您说fetch('data.json')时,您实际上是在请求http://yourdomain.com/data.json,因为它与您提出请求的页面有关。您应该以正斜杠开头,这将指示路径相对于域根:fetch('/js/data.json')。或者完全符合您的域名fetch('http://yourdomain.com/js/data.json')

理解为什么会出现这种情况的一个简单方法是考虑如果我们在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模块,因此相对路径的概念在概念上更清晰。

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

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
  })