NextJS+Prisma场景下查询记录后如何非阻塞将views计数+1?
NextJS + Prisma 实现非阻塞浏览量计数方案
核心思路
要避免阻塞前端响应,核心原则是不要等待计数更新操作完成再返回数据,利用Node.js异步非阻塞的特性,将更新逻辑放到后台执行,同时用Prisma的原子操作保证计数准确性。
实现代码
Pages Router 版本
// pages/api/[recordType]/[id].js import prisma from '@/lib/prisma' export default async function handler(req, res) { const { id, recordType } = req.query // 1. 先查询需要返回的记录数据 const record = await prisma[recordType].findUnique({ where: { id: Number(id) } }) if (!record) { return res.status(404).json({ error: '记录不存在' }) } // 2. 不等待更新操作完成,直接丢到后台执行 prisma[recordType].update({ where: { id: Number(id) }, // 用Prisma内置的increment原子操作,避免并发竞态问题 data: { views: { increment: 1 } } }).catch(err => { // 单独捕获更新错误,避免未捕获异常导致服务崩溃 console.error('浏览量更新失败:', err) }) // 3. 直接返回查询到的记录,响应速度不受更新逻辑影响 return res.status(200).json(record) }
App Router 版本(NextJS 13.4+)
推荐用官方提供的unstable_after钩子,确保更新逻辑在响应完全返回后执行,逻辑更可控:
// app/api/[recordType]/[id]/route.js import prisma from '@/lib/prisma' import { unstable_after as after } from 'next/server' export async function GET(req, { params }) { const { id, recordType } = params const record = await prisma[recordType].findUnique({ where: { id: Number(id) } }) if (!record) { return Response.json({ error: '记录不存在' }, { status: 404 }) } // 响应返回后自动执行更新逻辑 after(() => { prisma[recordType].update({ where: { id: Number(id) }, data: { views: { increment: 1 } } }).catch(err => console.error('浏览量更新失败:', err)) }) return Response.json(record) }
注意事项
- 不要使用「先查views数值 → 手动加1 → 再更新」的写法,并发场景下会出现计数不准的问题,
increment是数据库层面的原子操作,完全规避竞态问题 - 如果业务对数据一致性要求极高,不能接受极端场景下更新丢失的情况,可以引入轻量任务队列缓存更新请求,批量写入数据库,进一步降低数据库压力,普通业务场景上述写法已经足够稳定
- 不要将更新操作和查询操作放在同一个事务里等待执行,那样会阻塞响应返回,失去非阻塞的意义
内容的提问来源于stack exchange,提问作者Harsha M V
相关产品推荐
相关产品推荐

