Инициализировать URQL для Svelte асинхронным способом (мне нужно разделить schema.json на отдельный кусок)

Я использую Svelte и URQL.

Я использую здесь стройный пример из папки ваших пакетов, за исключением того, что я создаю format: 'esm' в моем rollup.config.js.

Мой накопительный пакет уже разделяет мой последний пакет на части, когда я использую import('./Component.svelte') в моем коде.

Что мне трудно сделать, так это асинхронно инициализировать urql, например:

import { initClient, dedupExchange, fetchExchange } from '@urql/svelte'
import { cacheExchange } from "@urql/exchange-graphcache";

const exchanges = [
  cacheExchange({
    resolvers: { /*... my resolvers*/ },
    schema // I need this async, something like: await import('./schema').then(result => result.default)
  }),
  fetchExchange
]

export function initURQL () {
  initClient({
    url: 'http://localhost/graphql',
    exchanges
  })
}

Если я использую что-то вроде:

export async function initURQL () {
  const schema = await import('./schema.json').default

  const exchanges = [
  cacheExchange({
    resolvers: {},
    schema
  }),
  fetchExchange
  ]
  initClient({
    url: 'http://localhost/graphql',
    exchanges
  })
}`

и позвонить из App.svelte с участием ;(async () => await initURQL())() это дает мне ошибку:

Uncaught (in promise) Error: Function called outside component initialization

Как я могу это исправить?

1 ответ

Я не использую URQL, но тоже столкнулся с этой ошибкой.

К сожалению, позвонить нельзя getContext или же setContext (который является то, что initClient в urql/packages/svelte-urql/src/context.ts звонки) асинхронно.

https://svelte.dev/docs#setContext:

Как и функции жизненного цикла, это должно вызываться во время инициализации компонента.

https://github.com/timhall/svelte-apollo/issues/9#issuecomment-646184888 отвечает на очень похожий вопрос и, надеюсь, указывает на подходящий обходной путь для вас:

это происходит с getClient и setClient, потому что это тонкий контекст, который доступен только при инициализации (построении) компонента и не может быть в обработчике событий. см. ответ на проблему регистрации пользователя Svelte с установкой значения хранилища. Скорее всего, происходит то, что вы вызываете его в асинхронном событии su как on:click, onMount, onDestroy, когда оно недоступно. Решением для этого является сохранение вашего клиента как магазина в контексте согласно https://svelte.dev/tutorial/context-api.

В целом это должно выглядеть примерно так:

setClient(writable(apolloClient));

let client
getClient().subscribe((_client) => client = _client);
Другие вопросы по тегам