如何使用 svelte/store 处理动态数组
我想从不同的 API 接收多个数据并将其放在一个大数组中。该数组应该可供不同的组件访问。如果调用所有 API 并收集数据,则组件应列出该数组。
我改编了 REPL 中的代码并添加了一个迭代,以调用每个 API。数组将被填充,但组件不显示列表。首先,我认为它与反应性/更新数组有关,但它也不会工作。
import { writable } from 'svelte/store'
export const API_LIST = [
"http://example1.com/api/",
"http://example2.com/api/"
];
export function readAll() {
const { subscribe, update, set } = writable([])
return {
subscribe,
init: async () => {
let alldata = [];
API_LIST.forEach(async function(apiurl) {
const res = await fetch(apiurl)
if (!res.ok) throw new Error('Bad response')
alldata.push( await res.json() );
alldata = alldata;
});
set(alldata);
return alldata;
}
}
}
export const api_store = readAll()
我的组件:
<script>
import { api_store } from 'reader.js';
</script>
<div>
{#await api_store.init()}
<p>wait for reading...</p>
{:then}
<ul>
{#each $api_store as item}
<li>
{item}
</li>
{/each}
</ul>
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}
</div>
调用所有API并构建数组后,“等待读取”消失,但显示的列表为空。我可以使用 {console.info($api_store)} 查看数组内容,因此数据存在。但为什么它没有出现在我的组件列表中?
I would like to receive several data from different APIs and put it together in one big array. This array should be accessable for different components. The components should list the array, if all APIs are called and the data was collected.
I adapted the code from REPL and added a iteration, to call each API. The array will be filled, but the component is not showing the list. First, I thought its related to reactivity / updating arrays, but it also wont work.
import { writable } from 'svelte/store'
export const API_LIST = [
"http://example1.com/api/",
"http://example2.com/api/"
];
export function readAll() {
const { subscribe, update, set } = writable([])
return {
subscribe,
init: async () => {
let alldata = [];
API_LIST.forEach(async function(apiurl) {
const res = await fetch(apiurl)
if (!res.ok) throw new Error('Bad response')
alldata.push( await res.json() );
alldata = alldata;
});
set(alldata);
return alldata;
}
}
}
export const api_store = readAll()
My component:
<script>
import { api_store } from 'reader.js';
</script>
<div>
{#await api_store.init()}
<p>wait for reading...</p>
{:then}
<ul>
{#each $api_store as item}
<li>
{item}
</li>
{/each}
</ul>
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}
</div>
After all APIs are called and the array is build up, the "wait for reading" disappears, but the list showed is empty. I can see the array content with {console.info($api_store)}, so the data is present. But why is it not showing up in my component list?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当您使用
.foreach()
方法并为其提供异步回调时,执行了调用
该代码在
alldata
数组已满之前 。(这是因为 NodeJS 内部的工作方式 - 在调用堆栈为空之前不会调用回调函数)
您可以通过将硬编码的随机值放入
alldata
数组中来测试它。您将看到随机值将出现在浏览器中。如果您将
.forach()
调用替换为常规for
循环您将阻止代码在对
fetch()
的所有调用完成之前返回。尝试将您的代码替换为以下内容:
reader.js:
Component.svelte:
这应该可以工作:)
When you use the
.foreach()
method and give it an async callback,the code executed the call to
and
before
alldata
array was full.(That is because how NodeJS internally works - the callback functions will not be called until the call stack is empty)
You can test it by putting hard-coded, random values in the
alldata
array. You will see the random values will appear inside the browser.If you will replace the
.forach()
call to regularfor
loopyou will prevent the code to return before all calls to
fetch()
will be finished.Try to replace your code to the following:
reader.js:
Component.svelte:
This should work :)
从
init()
返回alldata
是不必要的,它没有被使用除了等待所有数据的
for 循环
之外,还可以使用Promise.all()
-> REPL
Returning
alldata
frominit()
isn't necessary, it's nowhere usedAlternatively to the
for loop
waiting for all data could also be handled withPromise.all()
-> REPL