javascript:仅在结果准备好时更新DOM
javascript: Update the DOM only when the result is ready
我有一些 api 端点。
一个 returns 所有服务器详细信息 (https://dnscheck.io/api/serverDetails/)
其他是 server specific
端点。 (https://dnscheck.io/api/query/?id=2&type=A&hostname=test.com) 对于每个 server_Id(我从 serverDetails
端点获得),我必须调用每个 api 端点。
我所做的是。
我遍历结果数组(我从 serverDetails
端点获得)
并且对于循环的每次迭代,我调用每个端点以获取 ip。
循环:
for (const [index, item] of data.entries()) {
const res = await fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
);
const result = await res.json();
renderResult(result, item, index);
}
渲染函数:
const renderResult = (result, data, index) => {
const ip = document.querySelector(`.ip-address${index + 1}`);
ip.innerHTML = result.answers[0].address;
};
这样,结果就会同步显示在DOM中。 (一个接一个)
但是,我想要的是,一旦结果准备就绪,就用结果更新 dom。
我能做什么?
您可以通过在数组上使用 map
并在数组中使用 fetch
来并行执行它们。您可以通过使用 Promise.all
观察整体结果来了解它们何时全部完成:
await Promise.all(
data.entries().map(async (index, item) => {
const res = await fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
);
// You need to check `res.ok` here
const result = await res.json();
renderResult(result, item, index);
)
);
请注意,如果任何输入承诺被拒绝,Promise.all
将立即拒绝其承诺。如果您想知道什么成功什么失败,请改用 allSettled
:
const results = await Promise.allSettled(
data.entries().map(async (index, item) => {
const res = await fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
);
// You need to check `res.ok` here
const result = await res.json();
renderResult(result, item, index);
)
);
// Use `results` here, it's an array of objects, each of which is either:
// {status: "fulfilled", value: <the fulfillment value>}
// or
// {status: "rejected", reason: <the rejection reason>}
关于我的“你需要检查 res.ok
此处”的注释:不幸的是,这是 fetch
API 中的一把手枪。它只在 network 失败时拒绝它的承诺,而不是 HTTP 错误。因此 404
会产生一个已兑现的承诺。我写一下 here。通常最好的办法是调用包装函数,例如:
function fetchJSON(...args) {
return fetch(...args)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`); // Or an error subclass
}
return response.json();
});
}
不要使用 await
,因为那样会阻塞 for
循环并对结果进行排序。请改用 .then()
。
for (const [index, item] of data.entries()) {
fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
).then(res => res.json())
.then(result => renderResult(result, item, index));
}
我有一些 api 端点。
一个 returns 所有服务器详细信息 (https://dnscheck.io/api/serverDetails/)
其他是 server specific
端点。 (https://dnscheck.io/api/query/?id=2&type=A&hostname=test.com) 对于每个 server_Id(我从 serverDetails
端点获得),我必须调用每个 api 端点。
我所做的是。
我遍历结果数组(我从 serverDetails
端点获得)
并且对于循环的每次迭代,我调用每个端点以获取 ip。
循环:
for (const [index, item] of data.entries()) {
const res = await fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
);
const result = await res.json();
renderResult(result, item, index);
}
渲染函数:
const renderResult = (result, data, index) => {
const ip = document.querySelector(`.ip-address${index + 1}`);
ip.innerHTML = result.answers[0].address;
};
这样,结果就会同步显示在DOM中。 (一个接一个)
但是,我想要的是,一旦结果准备就绪,就用结果更新 dom。
我能做什么?
您可以通过在数组上使用 map
并在数组中使用 fetch
来并行执行它们。您可以通过使用 Promise.all
观察整体结果来了解它们何时全部完成:
await Promise.all(
data.entries().map(async (index, item) => {
const res = await fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
);
// You need to check `res.ok` here
const result = await res.json();
renderResult(result, item, index);
)
);
请注意,如果任何输入承诺被拒绝,Promise.all
将立即拒绝其承诺。如果您想知道什么成功什么失败,请改用 allSettled
:
const results = await Promise.allSettled(
data.entries().map(async (index, item) => {
const res = await fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
);
// You need to check `res.ok` here
const result = await res.json();
renderResult(result, item, index);
)
);
// Use `results` here, it's an array of objects, each of which is either:
// {status: "fulfilled", value: <the fulfillment value>}
// or
// {status: "rejected", reason: <the rejection reason>}
关于我的“你需要检查 res.ok
此处”的注释:不幸的是,这是 fetch
API 中的一把手枪。它只在 network 失败时拒绝它的承诺,而不是 HTTP 错误。因此 404
会产生一个已兑现的承诺。我写一下 here。通常最好的办法是调用包装函数,例如:
function fetchJSON(...args) {
return fetch(...args)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`); // Or an error subclass
}
return response.json();
});
}
不要使用 await
,因为那样会阻塞 for
循环并对结果进行排序。请改用 .then()
。
for (const [index, item] of data.entries()) {
fetch(
`https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
).then(res => res.json())
.then(result => renderResult(result, item, index));
}