我真的不知道问题是什么,但情况是这样的:
我有一个自定义存储,其中包含一个从 API 获取数据的数组。在我的主 +page.svelte 文件中,我在
onMount()
中初始化此商店并显示其内容。
这完全按照预期工作 - 我的数据出现在页面上 - 但是,一旦我重新加载页面或编译/保存,它就好像我的存储为空(没有错误消息,但也没有数据)。记录我商店的内容显示一个空数组 (
Array []
),但它填充了内容:
但是,一旦我修改此 +page.svelte(即使只是在
script
标签内部或外部添加注释),我的数据就会出现。记录后,它确实正确显示了一个填充的数组(Array(3) [ {...}, {...}, {...} ]
):
基本上,无论我在做什么,如果我不修改这个主页,它的行为就不会正确。
我的项目是使用 sveltekit bootstrap
npm create svelte@latest
选择 typescript、eslint 和 prettier 创建的,并且我添加了 SCSS。我一直在控制台中看到“vite”,所以我猜它也在那里?
我处于开发模式(我运行了
npm run dev
),一切正常,没有任何编译问题。
我已经尝试过查看一些配置文件,但老实说我什么都不明白。
同样,我已经尝试过在互联网上查找,但由于我无法真正定义问题,所以有点困难。
有人 IRL(作为 C 开发人员工作,所以他们无能为力)建议这是一个编译器问题,但真的是这样吗?如果是这样,我可以做些什么吗?
我不得不提的是,除了基本脚本之外,我真的不知道任何技术,所以请 ELI5。
+page.svelte
<script lang="ts">
import { onMount } from "svelte";
import { meals } from "../store/meals";
import MealCard from "./MealCard.svelte";
onMount( () => {
meals.initialise();
});
</script>
<h1>Today's Selection</h1>
<div class="list">
{#each $meals as meal}
<MealCard meal={meal}/>
{/each}
</div>
meal.ts
(商店)- 为了清楚起见,输入“remove”
import { writable } from "svelte/store";
function createMeals() {
const meals = [{
id: "",
name: "",
preview: "",
ingredients: [],
tags: [],
category: "",
origin: "",
source: "",
video: "",
instructions: "",
locked: false
}];
const nbOfMeals = 3;
const {subscribe} = writable(meals);
return {
subscribe,
add: (meal) => {
meals.push(meal);
},
initialise: async () => {
if (meals.length === nbOfMeals) {
return;
}
for (let iMeal = 0; iMeal < nbOfMeals; iMeal++) {
getMeal();
}
meals.shift();
}
}
}
export const meals = createMeals();
async function getMeal() {
const meal = {
id: "1",
name: "",
preview: "",
ingredients: [""],
tags: [],
category: "",
origin: "",
source: "",
video: "",
instructions: "",
locked: false,
};
const url = "https://www.themealdb.com/api/json/v1/1/random.php";
await fetch(url)
.then((response) => response.json())
.then((data) => {
const _data = data.meals[0];
meal.id = _data.idMeal;
meal.name = _data.strMeal;
meal.preview = _data.strMealThumb;
const tags = _data.strTags;
if (tags) {
meal.tags = tags.split(",");
}
meal.category = _data.strCategory;
meal.origin = _data.strArea;
meal.source = _data.strSource;
meal.video = _data.strYoutube;
meal.instructions = _data.strInstructions;
meal.ingredients = [""];
let iIngr = 1;
while (_data["strIngredient" + iIngr]) {
let toAdd;
const regexp = /\d|¼|½|¾|(\w+ of)/;
if (regexp.test(_data["strMeasure" + iIngr])) {
toAdd =
_data["strMeasure" + iIngr] +
" " +
_data["strIngredient" + iIngr];
}
else if (/[^\w]/.test(_data["strMeasure" + iIngr])) {
toAdd = _data["strIngredient" + iIngr];
}
else {
toAdd =
_data["strIngredient" + iIngr] +
" (" +
_data["strMeasure" + iIngr].toLowerCase() +
")";
}
meal.ingredients.push(toAdd);
iIngr++;
}
meal.ingredients.shift();
meals.add(meal);
});
}
[...]一旦我重新加载页面或编译/保存,它就好像我的商店是空的[...]
这可能是由于服务器端渲染造成的。当您的 Web 浏览器首次显示页面/重新加载页面时,您的 Svelte 应用程序将在服务器上运行,并且服务器会发回为其生成的 HTML 代码。此后,Web 浏览器将开始运行您的 Svelte 应用程序本身(如果在 Web 浏览器中启用了客户端 JS)。
服务器将在您的商店完全加载之前发回页面的 HTML 代码。在
onMount()
中,您调用 meals.initialize()
,但在服务器上,永远不会调用 onMount()
。即使是这样,您也需要在 await
中的 getMeal()
上使用 initialize()
(但是您可能还想使用 Promise.all(),因此您同时运行所有承诺时间)。
您能确认这是您遇到的问题吗?如果这不是问题,不想浪费时间建议不同的解决方案^^
在
getMeal()
中,如果您使用 then()
,则不应使用 catch()
/ await
,而应使用 try
和 catch
。