Reputation: 13290
I would like to know the proper way to have a pagination, specifically get the next page and let user know about it in the response. I also don't want to disclose the count
value in the response.
So my current implementation has this reponse:
{
"offset": 0,
"count": 8,
"nextPageOffset": 100,
"categories": [
{
......
But I realized my value for nextPageOffset
is just so wrong, and may produce bug, like the user may skip some data.
const nextPageOffset = offset + limit
How do I do it?
Here's my controller:
// Get all the categories.
exports.getCategories = (req, res) => {
const offset = parseInt(req.query.offset, 10)
const limit = parseInt(req.query.limit, 10)
db.Category.findAndCountAll({ where: {}, offset: offset, limit: limit })
.then(data => {
const rows = data.rows
const count = data.count
const object = { }
let nextPageOffset = offset + limit
//if count >
object.offset = offset
object.count = count
object.nextPageOffset = nextPageOffset
object.categories = rows
res.send(object)
})
.catch(err => {
console.log("Error get categories: " + err.message)
res.status(500).send({
message: "An error has occured while retrieving data."
})
})
}
Upvotes: 0
Views: 3800
Reputation: 75103
my approach is to make all my calls the same across any route response that uses pagination, for such my projects end up looking like this
https://github.com/balexandre/so61791627
where, in your example, I would write:
const listAllProducts = async (req, res) => {
const page = util.parser.tryParseInt(req.query.page, 0);
const limit = util.parser.tryParseInt(req.query.limit, 10);
try {
const result = await db.products.findAndCountAll({
where: {
active: '1',
},
offset: limit * page,
limit: limit,
order: [["id", "ASC"]],
});
res.json(util.response.paging(result, page, limit));
} catch (err) {
res.json({ error: err.message });
}
};
and to be consistent, I would make my response look like
exports.paging = (sequelizeResult, page, limit) => ({
page: page,
limit: limit,
total: sequelizeResult.count,
data: sequelizeResult.rows,
})
that way you don't prefix the data
with categories
as you currently have, and if it's for example users
or products
the "schema" would change...
NOTE: it is also common to encounter result
instead of data
routes would work like
GET /products
or
GET /products?limit=2&page=2
and the output would be, for GET /products?limit=2&page=2
HTTP/1.1 200 OK
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: application/json; charset=utf-8
Content-Length: 237
ETag: W/"ed-gK+xNNQgqp7jq/ZbZ3qja3u0680"
Date: Thu, 14 May 2020 09:36:55 GMT
Connection: close
{
"page": 2,
"limit": 2,
"total": 9,
"data": [
{
"id": 5,
"name": "Product 5",
"description": "Description for product 5",
"price": "1.25",
"active": true
},
{
"id": 6,
"name": "Product 6",
"description": "Description for product 6",
"price": "6.55",
"active": true
}
]
}
Upvotes: 2