To strategier: offset-basert (limit/offset) og cursor-basert. GraphQL har ingen innebygd paginering, men fellesskapsstandarden er Relay Connection-spesifikasjonen, som formaliserer cursor-paginering.
To strategier: offset-basert (limit/offset) og cursor-basert. GraphQL har ingen innebygd paginering, men fellesskapsstandarden er Relay Connection-spesifikasjonen, som formaliserer cursor-paginering.
items(limit: 10, offset: 20)) er enkelt, men bryter sammen på levende data: hvis en rad settes inn mens brukeren blar, forskyves elementene og du ser duplikater eller hull. Det blir også tregt ved dype offsets (databasen skanner fortsatt de hoppede radene).En connection pakker listen inn i edges (hver med en cursor og en node) pluss pageInfo:
type Query {
posts(first: Int!, after: String): PostConnection! # first = sidestørrelse, after = cursor
}
type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
}
type PostEdge {
cursor: String! # ugjennomsiktig token for DENNE nodens posisjon
node: Post! # selve elementet
}
type PageInfo {
endCursor: String # mat dette tilbake som 'after' for neste side
hasNextPage: Boolean! # så klienten vet når den skal stoppe
}
// resolver: hent ÉN ekstra rad for å beregne hasNextPage billig
const rows = await db.posts.find({ after: args.after, limit: args.first + 1 });
const hasNextPage = rows.length > args.first;
const page = rows.slice(0, args.first);
return {
edges: page.map((p) => ({ node: p, cursor: encodeCursor(p.id) })),
pageInfo: { endCursor: page.at(-1) && encodeCursor(page.at(-1).id), hasNextPage },
};
Cursoren er ugjennomsiktig — vanligvis en base64 av sorteringsnøkkelen — så klienter behandler den som et token, ikke et tall.
Å velge offset kontra cursor viser at du forstår konsistens under samtidige skrivinger og ytelse på dype sider. Å kjenne Relay-connection-formen er viktig fordi Apollo-/Relay-klienter har innebygd cache-håndtering for den.
Et bibliotek av IT-intervjuspørsmål med detaljerte svar — fra Junior til Senior.
Doner