在组件生命周期之外从 SvelteKit 的 $app/stores 获取值

Get values from SvelteKit's $app/stores outside of the lifecycle of a component

我的 Svelte 组件像这样导入可读存储:

import { classes, locations, schedule } from 'stores.ts'

在 stores.ts 中,我想构建 URL 以使用来自 $app/stores.

的 page.host 动态获取
// Note: this is not a Svelte component; it's stores.ts
import { readable } from 'svelte/store'
import { getStores } from '$app/stores'
const { page } = getStores()
let FQDN
page.subscribe(({ host }) => {
  FQDN = host
})

const getArray = async (url) => {
  const response: Response = await fetch(url)
  if (!response.ok) throw new Error(`Bad response trying to retrieve from ${url}.`)
  return await response.json()
}

const getReadableStore = (url: string) => readable([], set => {
  getArray(`http://${FQDN}${url}`)
    .then(set)
    .catch(err => console.error('Failed API call:', err))
  return () => {}
})

export const classes = getReadableStore('/api/class/public.json')
export const locations = getReadableStore('/api/location/public.json')
export const schedule = getReadableStore('/api/schedule/public.json')

第六行抛出这个错误...

Error: Function called outside component initialization at get_current_component (/Users/nates/dev/shy-svelte/node_modules/svelte/internal/index.js:652:15) at Proxy.getContext (/Users/nates/dev/shy-svelte/node_modules/svelte/internal/index.js:685:12) at Module.getStores (/.svelte-kit/dev/runtime/app/stores.js:17:26) at eval (/src/stores.ts:6:38) at instantiateModule (/Users/nates/dev/shy-svelte/node_modules/@sveltejs/kit/node_modules/vite/dist/node/chunks/dep-e9a16784.js:68197:166)

两个问题...

  1. 在组件上下文之外从 $app/stores 获取页面值的正确方法是什么?这可能吗? 下面的回答:不,这在组件上下文之外是不可能的。
  2. 如果我正在访问 SvelteKit 站点,假设 http://localhost:3000/somethinghttps://example.com 并且 Svelte 组件从 stores.ts 加载可读存储,[=45 中有没有办法=] 来确定加载组件(从 stores.ts 加载)的原始页面请求是 http 还是 https下面的回答:不,这在 stores.ts 中是不可能的 - 只能从一个组件。

更新: 根据反馈,我将在我的 .env 中设置一个名为 VITE_WEB_URL=http://localhost:3000 的值并更改它用于生产系统。这减少了代码行数,可能是一种更好的做法(欢迎评论)...

// revised stores.ts
import { readable } from 'svelte/store'

const { VITE_WEB_URL } = import.meta.env

const getArray = async (url) => {
  const response: Response = await fetch(url)
  if (!response.ok) throw new Error(`Bad response trying to retrieve from ${url}.`)
  return await response.json()
}

const getReadableStore = (url: string) => readable([], set => {
  getArray(`${VITE_WEB_URL}${url}`)
    .then(set)
    .catch(err => console.error('Failed API call:', err))
  return () => {}
})

export const classes = getReadableStore('/api/class/public.json')
export const locations = getReadableStore('/api/location/public.json')
export const schedule = getReadableStore('/api/schedule/public.json')
  1. 引用 svelte store 随处可见。 但是,使用 $: shorthand 语法仅适用于组件。

$: BASE = `http://${$page.host}`
  1. SvelteKit 似乎委托这个来获取确实
  1. 摘自https://kit.svelte.dev/docs#modules-$app-stores

Because of that, the stores are not free-floating objects: they must be accessed during component initialisation, like anything else that would be accessed with getContext.

  1. 因此,由于可读存储绑定到 svelte 组件的上下文,我建议您在 SvelteKit 网站的组件内订阅任何一种方式($ 或 .subscribe),然后发送协议值(http 或 https ) 作为更新时的参数,以便 stores.ts 将其存储在变量中。

不过好像SvelteKit没有提供protocol值,所以在page subscription中解析client端window.location.href然后发送