You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 16:36:03