Subcategories aren’t populating as s – Javascript

I’m trying to concatenate a string of <optgroup>s and <option>s based on categories and subcategories.

Currently, I am getting a string that has all the categories first then all of the subcategories. I need it to go category > subcategories for said category etc.

The backend has two tables, main categories, and subcategories.

Subcategory Table
  id
  title
  main_category_id

Main Category Table
  id
  title

In my code below, I am trying to loop through the main categories, adding them to an <optgroup>. Before moving to the next main category, I am getting the subcategories for each and adding them as <option>s.

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

async function getMainCategories() {
    const categoriesURL = "INSERT_URL"
    await fetch(categoriesURL)
      .then(response => response.json())
      .then(async categories => {
      await categories.sort(function(a, b) {
        var nameA = a.title.toUpperCase(); // ignore upper and lowercase
        var nameB = b.title.toUpperCase(); // ignore upper and lowercase
        if (nameA < nameB) {
          return -1;
        }
        if (nameA > nameB) {
          return 1;
        }

        // names must be equal
        return 0;
      }).map(async cat => {
        str += `<optgroup label="${cat.title}">`;
        await getSubcategories(cat.id);
        console.log(str)
        str += '</optgroup>';
      })
    });
    select.innerHTML = "<option disabled selected>Select a category</option>" + str;
}

async function getSubcategories(id) {
    let subcategoriesURL = `INSERT_URL?cat_id=${id}`;

    await fetch(subcategoriesURL)
      .then(response => response.json())
      .then(subcategories => {
      subcategories.sort(function(a, b) {
        var nameA = a.title.toUpperCase(); // ignore upper and lowercase
        var nameB = b.title.toUpperCase(); // ignore upper and lowercase
        if (nameA < nameB) {
          return -1;
        }
        if (nameA > nameB) {
          return 1;
        }

        // names must be equal
        return 0;
      }).map(sub => {
        return str += `<option value="${sub.id}">${sub.title}</option>`;
      })
    });
}
getMainCategories();