如何从 Sveltekit 版本 v1.0.0-next.287 中的端点获取数据

How to fetch data from endpoint in Sveltekit version v1.0.0-next.287

昨天我将 SvelteKit 版本从 v1.0.0-next.241 更新到 v1.0.0-next.287,因为我无法在组件中获取数据。我收到一条错误消息:JSON 中位置 0 的意外标记 <。 当我尝试解析响应时发生错误:await response.json() 自版本 241 以来,关于获取数据有什么变化吗?现在怎么办?

index.svelte

<script>
     import { session } from '$app/stores';
     import { onMount } from 'svelte';

            onMount(async () => {
                    const response = await fetch('/content', {
                            method: 'POST',
                            body: JSON.stringify({
                                user_id: $session.user.id
                            }),
                            headers: {
                                'Content-Type': 'application/json'
                            }
                        });
                        const data = await response.json(); // error occurs on this line
                });
</script>

index.js

export async function post({ request }) {
    const data = await request.json();
    try {
        if (data.user_id > 0) {
            let rows = await db.result;

            if (rows.length > 0) {
                return {
                    status: 200,
                    body: {
                        rows
                    },
                    headers: {
                        'Content-Type': 'application/json'
                    }
                };
            }

            return {
                status: 500,
                body: {
                    rows: [],
                    message: 'endp result err: ' + rows.message
                },
                headers: {
                    'Content-Type': 'application/json'
                }
            };
        }

        return {
            status: 400,
            body: {
                rows: [],
                message: 'User not authorized'
            },
            headers: {
                'Content-Type': 'application/json'
            }
        };
    } catch (err) {
        return {
            status: 500,
            body: {
                rows: [],
                message: 'endp other err: ' + err.message
            },
            headers: {
                'Content-Type': 'application/json'
            }
        };
    }
}

请求端点的 Postman 结果

<!DOCTYPE html>
<html lang="en" theme="white">

<head>
    <meta charset="utf-8" />
    <meta name="description" content="" />
    <link rel="icon" href="../img/favicon.png" />
    <link rel="stylesheet" href="../css/bootstrap-icons/bootstrap-icons.css" />
    <link rel="stylesheet" href="../css/charts/styles.min.css" />
    <link rel="stylesheet" href="../css/tiptap.css" />
    <link rel="stylesheet" href="../css/all.css" />
    <link rel="stylesheet" href="../css/global.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Lighthouse - Login</title>
    <style data-svelte>
        .action-text.s-dYWHY7G7-e5q.s-dYWHY7G7-e5q {
            font-size: 16px;
            line-height: 20px;
            text-decoration: none;
            color: #fff;
            width: 100%;
            padding: 0 1rem
        }

        .action-text.s-dYWHY7G7-e5q>span.s-dYWHY7G7-e5q {
            margin-left: 0.75rem;
            vertical-align: top
        }

        .s-dYWHY7G7-e5q.s-dYWHY7G7-e5q {}

        .action-link.s-u1xw7poppUIF {
            text-align: center;
            align-items: center;
            vertical-align: middle;
            justify-content: center;
            padding-top: 10px
        }

        .s-u1xw7poppUIF {}

        .search-wrapper.s-DzH6K7xlQw-L {
            position: relative;
            display: flex;
            max-width: 28rem;
            width: 100%;
            margin-left: 0.5rem;
            height: 3rem;
            background-color: #393939;
            color: #fff;
            transition: max-width 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
                background 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        .search-wrapper-hidden.s-DzH6K7xlQw-L {
            max-width: 3rem;
            background-color: #161616
        }

        .search-focus.s-DzH6K7xlQw-L {
            outline: 2px solid #fff;
            outline-offset: -2px
        }

        .search-wrapper-2.s-DzH6K7xlQw-L {
            display: flex;
            flex-grow: 1;
            border-bottom: 1px solid #393939
        }

        .btn-search.s-DzH6K7xlQw-L {
            width: 3rem;
            height: 100%;
            padding: 0;
            flex-shrink: 0;
            opacity: 1;
            transition: background-color 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
                opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        .btn-search-disabled.s-DzH6K7xlQw-L {
            border: none;
            pointer-events: none
        }

        .input-search.s-DzH6K7xlQw-L {
            font-size: 1rem;
            font-weight: 400;
            line-height: 1.375rem;
            letter-spacing: 0;
            color: #fff;
            caret-color: #fff;
            background-color: initial;
            border: none;
            outline: none;
            width: 100%;
            height: 3rem;
            padding: 0;
            transition: opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        .input-hidden.s-DzH6K7xlQw-L {
            opacity: 0;
            pointer-events: none
        }

        .btn-clear.s-DzH6K7xlQw-L {
            width: 3rem;
            height: 100%;
            padding: 0;
            flex-shrink: 0;
            opacity: 1;
            display: block;
            transition: background-color 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
                opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        .btn-clear.s-DzH6K7xlQw-L:hover {
            background-color: #4c4c4c
        }

        .btn-clear-hidden.s-DzH6K7xlQw-L {
            opacity: 0;
            display: none
        }

        .s-DzH6K7xlQw-L {}

        .subject-divider.s-CDH0hzNq6wMb.s-CDH0hzNq6wMb {
            color: #525252;
            padding-bottom: 4px;
            border-bottom: 1px solid #525252;
            margin: 32px 1rem 8px
        }

        .subject-divider.s-CDH0hzNq6wMb span.s-CDH0hzNq6wMb {
            font-size: 0.75rem;
            font-weight: 400;
            line-height: 1rem;
            letter-spacing: 0.32px;
            color: #c6c6c6
        }

        .s-CDH0hzNq6wMb.s-CDH0hzNq6wMb {}

        label.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            position: absolute;
            width: 1px;
            height: 1px;
            margin: -1px;
            padding: 0;
            overflow: hidden;
            white-space: nowrap;
            border: 0;
            visibility: inherit;
            clip: rect(0, 0, 0, 0)
        }

        [role="search"].s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            position: relative;
            display: flex;
            max-width: 28rem;
            width: 100%;
            margin-left: 0.5rem;
            height: 3rem;
            background-color: #393939;
            color: #fff;
            transition: max-width 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
                background 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        [role="search"].s-qIO5oRXzFdSn.s-qIO5oRXzFdSn:not(.active) {
            max-width: 3rem;
            background-color: #161616
        }

        [role="search"].active.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            outline: 2px solid #fff;
            outline-offset: -2px
        }

        [role="combobox"].s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            display: flex;
            flex-grow: 1;
            border-bottom: 1px solid #393939
        }

        input.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            width: 100%;
            height: 3rem;
            padding: 0;
            font-size: 1rem;
            font-weight: 400;
            line-height: 1.375rem;
            letter-spacing: 0;
            color: #fff;
            caret-color: #fff;
            background-color: initial;
            border: none;
            outline: none;
            transition: opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        input.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn:not(.active) {
            opacity: 0;
            pointer-events: none
        }

        button.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            width: 3rem;
            height: 100%;
            padding: 0;
            flex-shrink: 0;
            opacity: 1;
            transition: background-color 0.11s cubic-bezier(0.2, 0, 0.38, 0.9),
                opacity 0.11s cubic-bezier(0.2, 0, 0.38, 0.9)
        }

        .disabled.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            border: none;
            pointer-events: none
        }

        [aria-label="Clear search"].s-qIO5oRXzFdSn.s-qIO5oRXzFdSn:hover {
            background-color: #4c4c4c
        }

        .hidden.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            opacity: 0;
            display: none
        }

        ul.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            position: absolute;
            z-index: 10000;
            padding: 1rem 0;
            left: 0;
            right: 0;
            top: 3rem;
            background-color: #161616;
            border: 1px solid #393939;
            border-top: none;
            box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.5)
        }

        [role="menuitem"].s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {
            padding: 6px 1rem;
            cursor: pointer;
            font-size: 0.875rem;
            font-weight: 600;
            line-height: 1.29;
            letter-spacing: 0.16px;
            transition: all 70ms cubic-bezier(0.2, 0, 0.38, 0.9);
            display: block;
            text-decoration: none;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            color: #c6c6c6
        }

        .selected.s-qIO5oRXzFdSn.s-qIO5oRXzFdSn,
        [role="menuitem"].s-qIO5oRXzFdSn.s-qIO5oRXzFdSn:hover {
            background-color: #353535;
            color: #f4f4f4
        }

        [role="menuitem"].s-qIO5oRXzFdSn span.s-qIO5oRXzFdSn {
            font-size: 0.75rem;
            font-weight: 400;
            line-height: 1.34;
            letter-spacing: 0.32px;
            text-transform: lowercase;
            color: #c6c6c6
        }

        .s-qIO5oRXzFdSn.s-qIO5oRXzFdSn {}
    </style>
</head>

<body>
    <div id="svelte">


        <div class="auth-bg">
            <div class="auth-box p-4 m-auto">

                <div>
                    <div><img src="/img/logo_orig.png" alt="logo" height="96"></div>
                        <div class="py-2">
                            <div class="bx--form-item bx--text-input-wrapper">
                                <label for="ccs-0.gurrqcw5ltk" class="false bx--label">
        Username
      </label>
                                <div class="bx--text-input__field-outer-wrapper">
                                    <div class="bx--text-input__field-wrapper">


                                        <input id="ccs-0.gurrqcw5ltk" placeholder="Enter username..." type="email" value="" class="bx--text-input   ">


      </div>


                                    </div>
                                </div>
                            </div>
                            <div class="py-2">
                                <div class="bx--form-item bx--text-input-wrapper">
                                    <label for="ccs-0.xn3g2icn4s7" class="false bx--label">
        Password
      </label>
                                    <div class="bx--text-input__field-outer-wrapper">
                                        <div class="bx--text-input__field-wrapper">


                                            <input id="ccs-0.xn3g2icn4s7" placeholder="Enter password..." type="password" value="" class="bx--text-input   ">


      </div>


                                        </div>
                                    </div>
                                </div>
                                <div class="py-4">
                                    <button type="button" tabindex="0" class="bx--btn bx--btn--primary">
    Log in</button></div>
                                <div class="py-2">or
                                    <a href="/auth/register" class="bx--link     ">Register</a></div>
                                <div class="py-2">
                                    <a href="/auth/restore" class="bx--link     ">Forgot password?</a></div>
                            </div>
                        </div>
                        <div class="company-logo"><a href="https://www.fh-swf.de/en/"
                                target="_blank"><img src="/img/company-logo.png" alt="company-logo" height="64"></a>
                        </div>
                    </div>

                    <div class="bx--loading-overlay ">
                        <div aria-atomic="true" aria-labelledby="ccs-0.lnde8bksux9" aria-live="assertive"
                            class="bx--loading">
                            <label id="ccs-0.lnde8bksux9" class="bx--visually-hidden">Active loading indicator</label>
                            <svg viewBox="0 0 100 100" class="bx--loading__svg">
                                <title>Active loading indicator</title>
                                <circle cx="50%" cy="50%" r="44" class="bx--loading__stroke"></circle>
                            </svg></div>
                    </div>


                    <script type="module" data-hydrate="1xenv5n">
                        import { start } from "/@fs/Users/elshad/OneDrive/Projects/FH-SWF/StudentAssistant/LighthouseApp/.svelte-kit/runtime/client/start.js";
        start({
            target: document.querySelector('[data-hydrate="1xenv5n"]').parentNode,
            paths: {"base":"","assets":""},
            session: {authenticated:false},
            route: true,
            spa: false,
            trailing_slash: "never",
            hydrate: {
                status: 200,
                error: null,
                nodes: [
                    import("/src/routes/auth/__layout.reset.svelte"),
                        import("/src/routes/auth/login/index.svelte")
                ],
                params: {}
            }
        });
    </script>
                    <script type="application/json" data-type="svelte-props">
                        {}
                    </script>
                </div>
</body>

</html>

您还必须添加 accept headers 以向服务器表明您接受什么作为 return,默认情况下这是 html.

headers: {
  "content-type": "application/json",
  "accept": "application/json"
}

可能与此有关?我在研究如何 Post 文件到文件存储时偶然发现了它。

Breaking: use Request and Response objects in endpoints and hooks #3384