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

Node.js中如何从中间件取值并在其他模块函数中使用

问题描述

我在authenticateUser.js中创建了authenticateUser中间件,代码如下:

async function authenticateUser(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader) {
    return res.status(401).json({ message: 'Unauthorized access!' });
  }

  try {
    const accessToken = authHeader.split(' ')[1]; // 此处无需await,split为同步操作
    const payload = jwt.verify(accessToken, process.env.ACCESS_TOKEN_SECRET);
    const { email, uid, role } = payload;

    const user = await UserClient.findOne({ email });
    if (!user || user.accessToken !== accessToken) {
      return res.status(401).json({ message: 'Unauthorized access!' });
    }

    req.role = role;
    req.email = email;
    req.uid = uid;
    next();
  } catch (error) {
    return res.status(401).json({ message: 'Unauthorized access!' });
  }
}

在路由(如router.get("/user", authenticateUser, async(req,res)=>{}))中,我可以通过const email = req.email;获取用户邮箱,但想在sites.js的addSitesToUser函数中使用该邮箱值。函数代码如下:

async function addSitesToUser() {
  try {
    // <-------需要在此处使用email值-------->
    const userData = await UserClient.findOne({email});

    if(!userData.siteList || userData.siteList.length === 0){
      const updatedSites = await UserClient.findOneAndUpdate(
        { email },
        { $push: { siteList: { $each: sites } } },
        { upsert: true,new: true }
      );
    } else{
      const existingSiteIds = userData.siteList.map(site => site.siteId);
      const newSites = sites.filter(site => !existingSiteIds.includes(site.siteId));
      userData.siteList.push(...newSites);
      await userData.save();
    }
  } catch (error) {
    console.error('Error adding sites');
  }
}

我在index.js中通过await addSitesToUser();调用该函数,请问如何在addSitesToUser中拿到用户邮箱?

解决方案

最直接可靠的方式是将邮箱作为参数传递给addSitesToUser函数,同时补充原函数中缺失的sites参数(原代码中sites未定义会导致报错),具体步骤如下:

1. 修改sites.js中的addSitesToUser函数

让函数接收email和sites两个参数,同时优化逻辑:

async function addSitesToUser(email, sites) {
  try {
    const userData = await UserClient.findOne({ email });

    if (!userData?.siteList || userData.siteList.length === 0) {
      await UserClient.findOneAndUpdate(
        { email },
        { $push: { siteList: { $each: sites } } },
        { upsert: true, new: true }
      );
    } else {
      const existingSiteIds = userData.siteList.map(site => site.siteId);
      const newSites = sites.filter(site => !existingSiteIds.includes(site.siteId));
      // 优化:仅当存在新站点时才执行保存操作,减少不必要的数据库请求
      if (newSites.length > 0) {
        userData.siteList.push(...newSites);
        await userData.save();
      }
    }
  } catch (error) {
    // 补充错误详情,方便排查问题
    console.error('Error adding sites:', error);
  }
}

module.exports = { addSitesToUser }; // 确保函数被导出供外部调用

2. 在调用时传入邮箱和站点数据

如果index.js的调用是在经过authenticateUser中间件的路由处理函数中,直接将req.email和站点数据传入即可:

// index.js中的路由处理逻辑示例
const { addSitesToUser } = require('./sites.js');

router.get("/user", authenticateUser, async(req, res)=>{
  // 定义要添加的站点数据
  const sites = [
    { siteId: 'site_001', name: '站点A' },
    { siteId: 'site_002', name: '站点B' }
  ];
  // 调用函数并传入邮箱和站点数据
  await addSitesToUser(req.email, sites);
  // 后续响应逻辑
  res.json({ message: '站点添加成功' });
});

额外优化提示

  • 原authenticateUser中const accessToken = await authHeader.split(' ')[1];的await是多余的,split为同步操作,可直接删除。
  • 错误捕获时打印具体错误信息,能大幅降低问题排查难度。

内容的提问来源于stack exchange,提问作者Ke_Sandaru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 00:55:19