Я работаю над приложением SvelteKit, в котором мне нужно получить список данных сообщений и избежать избыточных вызовов API.
Маршрут: all-posts/+page.svelte
fetchAllPostsData()
Маршрут: post/[id]/[title]/+page.svelte
fetchPostDataById(id)
Текущая реализация приводит к вызову 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-->
@ThomasHennes Спасибо, что указали на это! Вы были правы в том, что в первую очередь нужно получить список сообщений. Первоначально я сосредоточился на fetchPostDataById() для случая использования, когда пользователи делятся контентом через URL-адрес, и упустил общую картину. Я изменил свой вопрос для варианта использования списка, потому что это было бы более понятно.
Это немного сложнее, чем можно было подумать на первый взгляд. Чтобы оптимизировать получение данных, вам следует не только избегать дублирующих/ненужных запросов (цель вашего вопроса), но и избегать предоставления устаревших данных вашим пользователям. Короче говоря, вам нужно реализовать эффективный механизм кэширования данных ваших публикаций.
Хотя вы можете создать такой механизм вручную, используя хранилища Svelte, временные метки и т. д., Tanstack, создатели react-query
, выпустили библиотеку запросов и кэширования для Svelte, которая будет обрабатывать сложные детали запуска эффективного кэширования за вас и сделать вашу жизнь намного проще.
Tanstack также опубликовал несколько примеров использования, которые могут оказаться очень полезными при реализации вашего собственного варианта использования.
Если вы по-прежнему предпочитаете идти по ручному маршруту, я думаю этот другой ТАК-ответ может оказаться хорошей отправной точкой.
Надеюсь, вы найдете это полезным. Удачи!
Как вообще перейти к маршруту
/post/[id]
? Якобы из какого-то списка? В идеале вы хотели бы получать заголовки вместе с идентификаторами при создании списка, что позволит вам сразу же отформатировать заголовки для использования URL-адресов, полностью пропустить шаг/post/[id]
и вместо этого перейти прямо к маршруту/post/[id]/[title]
.