Порядок содержимого массива не соответствует в ответе JSON - PullRequest
1 голос
/ 10 марта 2019

Итак, у меня есть эта таблица вложенных множеств в Postgres, вот схема и данные . И у меня есть этот код функции контроллера ниже в моем приложении Express, чтобы получить вложенную категорию в виде массива, используя Knex и некоторую обработку обещаний:

const getCategories = (req, res, db) => {
  const products = []

  db.raw(`
    SELECT child.id, child.name, child.path
    FROM product_category parent
    JOIN product_category child
    ON child.lower BETWEEN parent.lower AND parent.upper
    WHERE parent.id = 1
      AND
        (
          SELECT COUNT(*)
          FROM product_category node
          WHERE child.lower BETWEEN node.lower AND node.upper
            AND node.lower BETWEEN parent.lower AND parent.upper
        ) = 2 
  `)
  .then(categories => {
    if (categories.rows.length) {
      const categoryPromises = categories.rows.map(category => {
        return db.raw(`
          SELECT child.id, child.name, child.path
          FROM product_category parent
          JOIN product_category child
          ON child.lower BETWEEN parent.lower AND parent.upper
          WHERE parent.id = ${category.id}
          AND
            (
              SELECT COUNT(*)
              FROM product_category node
              WHERE child.lower BETWEEN node.lower AND node.upper
                AND node.lower BETWEEN parent.lower AND parent.upper
            ) = 2 
        `)
        .then(subcategories => {
          const categoryObject = { ...category, subcategories: [] }
          if (subcategories.rows.length) {
            subcategories.rows.map(subcategory => {
              categoryObject.subcategories.push(subcategory)
            })
            products.push(categoryObject)
          } else {
            res.status(400).json("No subcategories")
          }
        })
      })

      return Promise.all(categoryPromises)
      .then(() => res.json(products))

    } else {
      res.status(400).json("No categories")
    }
  })
}

У меня нет проблем с получением ответа, но порядок объектов первого уровня внутри массива не согласован. Иногда это так:

[
  {
    "id": 9,
    "name": "Other Products",
    "path": "other_products",
    "subcategories": [
      {
        "id": 10,
        "name": "Slides",
        "path": "slides"
      },
      {
        "id": 11,
        "name": "Buoys",
        "path": "buoys"
      }
    ]
  },
  {
    "id": 2,
    "name": "Boats",
    "path": "boats",
    "subcategories": [
      {
        "id": 3,
        "name": "Rescue Boats",
        "path": "rescue_boats"
      },
      {
        "id": 4,
        "name": "Dive Boats",
        "path": "dive_boats"
      },
      {
        "id": 5,
        "name": "Tamarans",
        "path": "tamarans"
      },
      {
        "id": 6,
        "name": "Dragon Boats",
        "path": "dragon_boats"
      },
      {
        "id": 7,
        "name": "Kayaks",
        "path": "kayaks"
      },
      {
        "id": 8,
        "name": "Speedboats",
        "path": "speedboats"
      }
    ]
  }
]

Или вот так:

[
  {
    "id": 2,
    "name": "Boats",
    "path": "boats",
    "subcategories": [
      {
        "id": 3,
        "name": "Rescue Boats",
        "path": "rescue_boats"
      },
      {
        "id": 4,
        "name": "Dive Boats",
        "path": "dive_boats"
      },
      {
        "id": 5,
        "name": "Tamarans",
        "path": "tamarans"
      },
      {
        "id": 6,
        "name": "Dragon Boats",
        "path": "dragon_boats"
      },
      {
        "id": 7,
        "name": "Kayaks",
        "path": "kayaks"
      },
      {
        "id": 8,
        "name": "Speedboats",
        "path": "speedboats"
      }
    ]
  },
  {
    "id": 9,
    "name": "Other Products",
    "path": "other_products",
    "subcategories": [
      {
        "id": 10,
        "name": "Slides",
        "path": "slides"
      },
      {
        "id": 11,
        "name": "Buoys",
        "path": "buoys"
      }
    ]
  }
]

Как мне сделать это согласованным? Может быть, это немного тривиально, но через некоторое время это немного раздражает. Заранее спасибо!

1 Ответ

0 голосов
/ 18 марта 2019

Я также попросил в r / learnprogramming subreddit, чтобы увеличить шансы получить ответ.Пользователь u / shhh-quiet дал хорошее решение .

По сути, это потому, что я написал плохой код в своем фрагменте.Я просто процитирую его полный ответ:

Я думаю, это то, что вы создаете массив продуктов из цепочки обещаний вложенных запросов.В зависимости от того, сколько времени занимают запросы, продукты будут иметь разные порядки.

Обычно это считается плохим при работе с обещаниями.Это в основном освобождает от порядка, установленного вами при использовании карты и Promise.all.

Вы должны изменить:

products.push(categoryObject)

... на:

return categoryObject

И измените:

return Promise.all(categoryPromises)
  .then(() => res.json(products))

... на:

return Promise.all(categoryPromises)
  .then(products => res.json(products))

И удалите:

const products = []

Редактировать: Просто чтобы было ясно,у него нет учетной записи StackOverflow, и он дал мне разрешение опубликовать свой ответ.

...