Как избежать избыточных вызовов API в SvelteKit при получении данных публикации

Я работаю над приложением SvelteKit, в котором мне нужно получить список данных сообщений и избежать избыточных вызовов API.

  1. Маршрут: all-posts/+page.svelte

    • Получает список сообщений с помощью fetchAllPostsData()
  2. Маршрут: post/[id]/[title]/+page.svelte

    • Снова извлекает данные публикации, используя fetchPostDataById(id)
    • Отображает полученные данные в DOM

Текущая реализация приводит к вызову fetchAllPostsData(), а затем повторному вызову fetchPostDataById(id), что неэффективно. Вот соответствующий код:

all-posts/+page.svelte:

<script>
    import { onMount } from 'svelte';
    import { fetchAllPostsData } from './fetch-post-data';

    let postsDataArr = [];

    onMount(async () => {
        postsDataArr = await fetchAllPostsData();
    });
</script>

<section>
    <ul>
        {#each postsDataArr as post}
            <li><a href = {`/post/${post.id}/${post.title.replace(/[\s ]/g, '-')}`}>{post.title}</a></li>
        {/each}
    </ul>
</section>

post/[id]/[title]/+page.svelte:

<script>
    import { onMount } from 'svelte';
    import { page } from '$app/stores';
  import { fetchPostDataById } from '../fetch-post-data';


    let id;
    /**
     * @type {any}
     */
    let data;

    $: id = $page.params.id;

    onMount(async () => {
        data = await fetchPostDataById(id);
    });
</script>

<section>
    {#if data}
    <div>
        <div>{@html data.html}</div>
    </div>
    {/if}
</section>

Дополнительный контекст:

Я не хочу полностью удалять функцию fetchPostDataById(id), так как это важно в тех случаях, когда пользователи делятся прямой ссылкой на публикацию. В таких сценариях ссылка на публикацию должна получать данные публикации по идентификатору, чтобы гарантировать отображение правильных данных, даже если пользователь обращается к публикации напрямую через URL-адрес.

Вопрос:

Как я могу реорганизовать свой код, чтобы избежать повторного вызова API? Я хочу получить список сообщений один раз и использовать эти данные в обоих маршрутах без избыточной выборки.


Обновление после получения ответа и предложения

Теперь я использую TanStack Query в Svelte вместо того, чтобы каждый раз напрямую вызывать API. Подробнее читайте в официальном документе

<script lang = "ts">
  import { createQuery } from '@tanstack/svelte-query';

  // Define the options for the fetch request
  const options = {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({"limit":100})
  };

  // Fetch function to get paginated posts
  const fetchPaginatedPosts = async () => {
    try {
      const response = await fetch('http://localhost:4000/get-paginated-posts', options);
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
        const res = await response.json()
        console.info(res)

          /*
            res = {
              "posts": [
                  {
                      "id": "667776bcc5d22d6226f7647b",
                      "description": "Hello, this is me!",
                      "title": "My page is here!",
                      "update_count": 0,
                      "updated_at": "2024-06-23T10:13:32.190+00:00"
                      "created_at": "2024-06-23T10:13:32.190+00:00",
                      "created_by": "666ff11d406248baf2e87df4",
                  } ,{...}
              ],
              "nextToken": "667776bcc5d22d6226f7647b"
          }
          */
         
        return res;
    } catch (error) {
      console.error(error);
      throw error;
    }
  };

  // Create the query
  const query = createQuery({
    queryKey: ['posts'],
    queryFn: fetchPaginatedPosts,
    initialData: null,
  });

  // Access and log the posts data
  const result = $query.data
  console.info({result})
</script>

<!--html omitted-->

Как вообще перейти к маршруту /post/[id]? Якобы из какого-то списка? В идеале вы хотели бы получать заголовки вместе с идентификаторами при создании списка, что позволит вам сразу же отформатировать заголовки для использования URL-адресов, полностью пропустить шаг /post/[id] и вместо этого перейти прямо к маршруту /post/[id]/[title].

Thomas Hennes 22.06.2024 13:36

@ThomasHennes Спасибо, что указали на это! Вы были правы в том, что в первую очередь нужно получить список сообщений. Первоначально я сосредоточился на fetchPostDataById() для случая использования, когда пользователи делятся контентом через URL-адрес, и упустил общую картину. Я изменил свой вопрос для варианта использования списка, потому что это было бы более понятно.

kawa 22.06.2024 14:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это немного сложнее, чем можно было подумать на первый взгляд. Чтобы оптимизировать получение данных, вам следует не только избегать дублирующих/ненужных запросов (цель вашего вопроса), но и избегать предоставления устаревших данных вашим пользователям. Короче говоря, вам нужно реализовать эффективный механизм кэширования данных ваших публикаций.

Хотя вы можете создать такой механизм вручную, используя хранилища Svelte, временные метки и т. д., Tanstack, создатели react-query, выпустили библиотеку запросов и кэширования для Svelte, которая будет обрабатывать сложные детали запуска эффективного кэширования за вас и сделать вашу жизнь намного проще.

Tanstack также опубликовал несколько примеров использования, которые могут оказаться очень полезными при реализации вашего собственного варианта использования.

Если вы по-прежнему предпочитаете идти по ручному маршруту, я думаю этот другой ТАК-ответ может оказаться хорошей отправной точкой.

Надеюсь, вы найдете это полезным. Удачи!

Другие вопросы по теме