Docker 工兵:获得';“获取事件”&书信电报;url>&引用;导致网络错误响应:承诺被拒绝;码头工人之下

Docker 工兵:获得';“获取事件”&书信电报;url>&引用;导致网络错误响应:承诺被拒绝;码头工人之下,docker,svelte,sapper,Docker,Svelte,Sapper,设置: 我是Sapper(以及web开发)的新手。 我一直在学习Sapper并尝试构建一个web应用程序,包括: 数据库服务器(mysql) 后端(beego) 前端(工兵) 它们中的每一个都使用docker compose进行停靠,我有一个用户定义的网络。比如: version: '3' services: db: networks: - fullstack_network ... api: networks: - fullstack_

设置: 我是Sapper(以及web开发)的新手。 我一直在学习Sapper并尝试构建一个web应用程序,包括:

  • 数据库服务器(mysql)
  • 后端(beego)
  • 前端(工兵)
  • 它们中的每一个都使用docker compose进行停靠,我有一个用户定义的网络。比如:

    version: '3'
    services:
      db:
        networks:
          - fullstack_network
        ...
    
      api:
        networks:
          - fullstack_network
        ...
    
      frontend:
        environment:
          # The env variable will be used as the base URL to the backend (api)
          - API_ENDPOINT=http://api:8082
        depends_on:
          - api
        networks:
          - fullstack_network
        ...
    
    networks:
      fullstack_network:
    
    问题:

    在前端(已停靠),我有一个名为
    foo
    的页面。单击页面时,我希望对返回JSON的后端API进行API调用

    正如我一直试图实现的那样,我对preload函数进行API调用。 它总是抛出一个错误500:

    未捕获(承诺中)TypeError:无法获取

    我从控制台看到一条警告:

    “的获取事件”http://api:8082/v1/foo“导致网络错误响应:承诺被拒绝

    获得成功结果的唯一方法是刷新页面,这是不好的

    注意:如果前端没有被停靠,我根本不会遇到这个错误

    这是我的
    路线/foo.svelte

    <script context="module">
        import {API_ENDPOINT} from "../components/Config.js"
    
        export async function preload(page, {env}) {
            let api_endpoint = API_ENDPOINT;
    
            if (env['API_ENDPOINT'] !== undefined) {
                api_endpoint = env['API_ENDPOINT'];
            }
    
            let url = api_endpoint + "/v1/foo";
            // when dockerized, the url is "http://api:8082/v1/foo"
            // when it is not dockerized, the url is "http://localhost:8080/v1/foo", because I make the backend (api) accessible from the host machine. 
            const response = await this.fetch(url);
            if (response.ok) {
                const json = await response.json();
                return {
                     results: json
                };
            } else {
                throw new Error("Fetch foo failed!");
            }
        }
    </script>
    
    <script>
        export let results;
    </script>
    
    <svelte:head>
        <title>Foo</title>
    </svelte:head>
    <p>
        This is the foo overview.
    </p>
    
    {#await results}
        <p>fetching ...</p>
    {:then results}
        <pre>{JSON.stringify(results, null, 2)}</pre>
    {:catch error}
        <div class="error">Unable to fetch the data! <br/>
            {error}
        </div>
    {/await}
    
    
    从“./components/Config.js”导入{API_ENDPOINT}
    导出异步函数预加载(第页,{env}){
    设api_endpoint=api_endpoint;
    if(env['API_ENDPOINT']!==未定义){
    api_endpoint=env['api_endpoint'];
    }
    让url=api_endpoint+“/v1/foo”;
    //停靠时,url为“http://api:8082/v1/foo"
    //未停靠时,url为“http://localhost:8080/v1/foo,因为我使后端(api)可以从主机访问。
    const response=wait this.fetch(url);
    if(response.ok){
    const json=await response.json();
    返回{
    结果:json
    };
    }否则{
    抛出新错误(“获取foo失败!”);
    }
    }
    出口结果;
    福
    
    这是foo概述。
    

    {#等待结果} 获取

    {:然后是结果} {JSON.stringify(结果,null,2)} {:捕获错误} 无法获取数据
    {错误} {/等待}

    你能帮我找到根本原因和解决办法吗?感谢您对出现问题的原因作出解释。

    这似乎与苗条或赛珀无关。当您键入url
    http://api:8082/v1/foo
    在浏览器中,您是否可以获得所需的数据?如果不是,则表示在docker外部无法访问地址api:8082。谢谢!我重新阅读了预加载文档,预加载块中的代码可以在服务器或客户端浏览器中运行。当API调用在服务器上(docker容器内)运行时,
    http://api:8082
    是可访问的,因为前端与后端api共享同一网络。这就解释了刷新页面(即按下F5按钮)的原因。当代码在浏览器上运行时,
    http://api:8082
    不可访问。解决此问题的一种方法是为后端使用固定地址或FQDN,该地址或FQDN在docker容器内外均可访问。这似乎与Svelte或Sapper无关。当您键入url
    http://api:8082/v1/foo
    在浏览器中,您是否可以获得所需的数据?如果不是,则表示在docker外部无法访问地址api:8082。谢谢!我重新阅读了预加载文档,预加载块中的代码可以在服务器或客户端浏览器中运行。当API调用在服务器上(docker容器内)运行时,
    http://api:8082
    是可访问的,因为前端与后端api共享同一网络。这就解释了刷新页面(即按下F5按钮)的原因。当代码在浏览器上运行时,
    http://api:8082
    不可访问。解决此问题的一种方法是为后端使用固定地址或FQDN,该后端可在docker容器内外访问。