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

初始化前无法访问getSession:如何解决SWR/Passport.js循环依赖问题?

问题描述

集成MongoDB、Next.js与Passport.js开发应用时,启动项目尝试登录会触发500状态错误,错误信息如下:

Cannot access 'getSession' before initialization

背景说明

项目实现了一个调用/api/user接口的自定义hook,校验req.user是否已被passport设置,根据返回结果生成对应user对象,存在user对象即可访问应用内的其他链接与路由。
初步怀疑是session.js文件中的getSession函数声明引发了循环依赖问题。

相关代码

session.js

import MongoStore from "connect-mongo";

import nextSession from 'next-session';

import { getMongoClient } from "./mongodb";

const mongoStore = MongoStore.create({
  clientPromise: getMongoClient(),
  stringify: false,
});

const getSession = nextSession({
  store: mongoStore,
  cookie: {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    maxAge: 2 * 7 * 24 * 60 * 60, // 2 weeks,
    path: "/",
    sameSite: "strict",
  },
  touchAfter: 1 * 7 * 24 * 60 * 60, // 1 week
});

export default function session(req, res, next) {
  getSession(req, res);
  next();
}

auth 中间件代码

包含passport引入、初始化及session配置:

import passport from '../lib/passport'
import session from '../lib/session'

const auths = [session, passport.initialize(), passport.session()];

export default auths;

Layout 组件代码

export default function Layout({ children, showFooter = false }) {

  const [user, { mutate }] = useCurrentUser();

  async function handleLogout() {
    axios
      .get('/api/logout').then(() => {
        mutate({ user: null })
        Router.push('/',)
      }).catch(err => console.log('err', err))
  }

  return <>
    <div className="shadow bg-base-200 drawer h-screen">
          <div className="flex-none hidden lg:block">
            <ul className="menu horizontal">

              {user
                ?
                <>
                  <li>
                    <Link href="/profile">
                      <a>Profile</a>
                    </Link>
                  </li>
                  <li>
                    <Link href="/dashboard">
                      <a>Dashboard</a>
                    </Link>
                  </li>
                  <li>
                    <a role="button" onClick={handleLogout}>
                      Logout
                    </a>
                  </li>
                  <li className="avatar">
                    <div className="rounded-full w-10 h-10 m-1">
                      <img src="https://i.pravatar.cc/500?img=32" />
                    </div>
                  </li></>
                :
                <>
                  <li>
                    <Link href="/login">
                      <a>Login</a>
                    </Link>
                  </li>
                  <li>
                    <Link href="/registration">
                      <a>Register</a>
                    </Link>
                  </li>
                </>
              }
            </ul>
          </div>
        </div>
  </>;
}

自定义hook代码

import useSWR from 'swr';

export const fetcher = (url) => {
  try {
    return fetch(url).then((res) => {
      console.log('res', res)
      return res.json()
    })
  } catch (error) {
    console.log('error', error)
  }
}
export function useCurrentUser() {
  const { data, mutate } = useSWR('/api/user', fetcher);
  const user = data?.user;
  return [user, { mutate }];
}

export function useUser(id) {
  const { data } = useSWR(`/api/users/${id}`, fetcher, {
    revalidateOnFocus: false,
  });
  return data?.user;
}

/api/user 接口代码

import nextConnect from 'next-connect'
import auth from '/middleware/auth'

const handler = nextConnect()

handler
  .use(auth)
  .get((req, res) => {
    console.log("req.user ", req.user);
    if (req.user) {
      res.json({ user: req.user })
    } else {
      res.json({ user: null })
    }
  })


export default handler
解决方案

该报错由两个核心配置错误导致,按以下步骤修复即可:

  1. 修复session.js的异步调用逻辑
    next-session返回的getSession是异步函数,原代码没有等待执行完成就调用了next(),会导致session初始化时序错误,修改session.js的导出中间件为异步逻辑:
export default async function session(req, res, next) {
  await getSession(req, res);
  next();
}
  1. 修复中间件数组的传入方式
    你导出的auth是多个中间件组成的数组,next-connect的use方法不支持直接传入数组,需要展开数组后传入,修改/api/user中的代码:
// 原代码 .use(auth) 替换为
.use(...auth)
  1. 可选排查循环依赖
    如果修复上述两个问题后依然报错,检查../lib/passport文件是否存在反向导入middleware/auth或lib/session的代码,移除循环依赖即可。

内容的提问来源于stack exchange,提问作者Antonio Pavicevac-Ortiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 21:54:03