JSON 响应中数组内容的顺序不一致
Order of array content is not consistent in JSON response
所以,我在 Postgres 中有这个嵌套集 table,here's the schema and data。我的 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"
}
]
}
]
如何使它保持一致?也许这有点微不足道,但一段时间后它会变得有点烦人。提前致谢!
I also asked in r/learnprogramming subreddit to increase the chances of it getting answered. User u/shhh-quiet gave a nice solution。
基本上,这是因为我在代码片段中编写了错误的代码。我只引用他的全部回答:
I think it's that you're building the products array from inside the
nested queries' promise chain. Depending on how long the queries take,
products will end up with different orderings.
This is generally considered bad when working with promises. It
basically breaks free of the ordering otherwise established by your
use of map and Promise.all.
You should change:
products.push(categoryObject)
...to:
return categoryObject
And change:
return Promise.all(categoryPromises)
.then(() => res.json(products))
...to:
return Promise.all(categoryPromises)
.then(products => res.json(products))
And remove:
const products = []
编辑:澄清一下,他没有 Whosebug 帐户,他允许我 post 他的回答。
所以,我在 Postgres 中有这个嵌套集 table,here's the schema and data。我的 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"
}
]
}
]
如何使它保持一致?也许这有点微不足道,但一段时间后它会变得有点烦人。提前致谢!
I also asked in r/learnprogramming subreddit to increase the chances of it getting answered. User u/shhh-quiet gave a nice solution。
基本上,这是因为我在代码片段中编写了错误的代码。我只引用他的全部回答:
I think it's that you're building the products array from inside the nested queries' promise chain. Depending on how long the queries take, products will end up with different orderings.
This is generally considered bad when working with promises. It basically breaks free of the ordering otherwise established by your use of map and Promise.all.
You should change:
products.push(categoryObject)
...to:
return categoryObject
And change:
return Promise.all(categoryPromises) .then(() => res.json(products))
...to:
return Promise.all(categoryPromises) .then(products => res.json(products))
And remove:
const products = []
编辑:澄清一下,他没有 Whosebug 帐户,他允许我 post 他的回答。