子类别未使用 fetch 填充

Subcategories aren't populating using fetch

我正在尝试创建具有从 API 中提取的子类别的 <optgroup>。目前,只有 <optgroup> 正在填充,子类别没有。

let select = document.querySelector("#category");
const categoriesURL = "INSERT_URL"
  
let str = "";

fetch(categoriesURL)
  .then(response => response.json())
  .then(data => {
    data.forEach(category => {
      let categoryTitle = category.title;
      str += `<optgroup label=${categoryTitle}></optgroup>`
      category.subcategories.forEach(sub => {
        let subcategories_id = sub.subcategories_id;
        let subcategoriesURL = `INSERT_URL/${subcategories_id}`;
        fetch(subcategoriesURL)
          .then(response => response.json())
          .then(subData => {
          str += `<option value=${sub.subcategories_id}>` + subData.title + "</option>";
        })
      })
  })
  select.innerHTML = "<option disabled selected>Select a category</option>" + str;
});

在字符串中定义 optgroup 时,您会立即打开和关闭 optgroup,有效地将每个选项放在 optgroup 之后。

str += `<optgroup label=${categoryTitle}></optgroup>`

将上述字符串中的 optgroup 保持打开状态。

然而,困难的部分是在子类别的所有 fetch 请求完成后 关闭字符串。我们可以用 Promise.all and Array#map.

来完成这个

循环遍历所有子类别 map 和 return Promise,循环中有 fetch return。当所有 fetch 请求完成后,代码将继续到 Promise.all 函数之后的 then 块。在该块中,您将收集到数组中的 所有 您的子类别的 ID 和标题。遍历数组以附加到您的字符串。

循环后,关闭optgroup元素。

fetch(categoriesURL)
  .then(response => response.json())
  .then(data => {
    data.forEach(category => {
      let categoryTitle = category.title;
      str += `<optgroup label=${categoryTitle}>`;

      Promise.all(category.subcategories.map(sub => {
        let subcategories_id = sub.subcategories_id;
        let subcategoriesURL = `INSERT_URL/${subcategories_id}`;

        return fetch(subcategoriesURL)
          .then(response => response.json())
          .then(({ title }) => ({
            title,
            id: subcategories_id
          }))
      })).then(subData => {
        subData.forEach(({ id, title }) => {
          str += `<option value=${id}>${title}</option>`;
        })
        
        str += '</optgroup>';
      });
    })

    select.innerHTML = "<option disabled selected>Select a category</option>" + str;
  });

不过,总的来说这是一个非常昂贵的脚本,因为它会创建大量请求。如果您对后端有任何发言权,那么我建议您在单个请求中发回所有数据,并根据该结果创建您的列表。