【问题标题】:javascript: Update the DOM only when the result is readyjavascript:仅在结果准备好时更新 DOM
【发布时间】:2021-08-22 15:33:54
【问题描述】:

我有一些 api 端点。

返回所有服务器详细信息 (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。

我能做什么?

【问题讨论】:

  • But, what I want is, update the dom with the result, as soon as the result is ready. 你的意思是当你在for 循环中发出的所有获取请求的结果s都准备好时?
  • 不是这样的。看看搜索结果是怎么来的。它们不同步。我要这个。 https://www.whatsmydns.net/

标签: javascript css api async-await dom-manipulation


【解决方案1】:

不要使用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));
}

【讨论】:

  • 建议添加错误处理,这样就不会出现未处理的拒绝,但绝对可以。
【解决方案2】:

您可以通过在数组上使用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();
    });
}

【讨论】:

  • 我想你忘了在 Array#map 回调中使用 async 关键字。另外,你需要return renderResult 编辑:我的错,不需要回报。
  • async 丢失,但 renderResult 不必返回 - 它似乎没有返回任何内容。
  • 谢谢@Andrew - 这很尴尬。 :D
  • @T.J.Crowder :(
  • 感谢第二次编辑@CherryDT!天哪,我今天没参加比赛,是吗?
猜你喜欢
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 2013-07-14
相关资源
最近更新 更多