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

调用findById()后打印find()结果显示undefined的问题排查

问题原因

你遇到的undefined问题,根源是**var声明变量的作用域特性**:

  • var是函数级作用域,整个for循环里只有一个i变量,所有循环迭代共享同一个i的引用。
  • findById是异步操作,它的then回调会在循环结束后才执行,这时候i已经变成了result.length(循环终止的条件),自然result[i]就指向了数组外的位置,返回undefined。
  • 而循环里的同步console.log是在当前迭代时执行的,此时i还是当前的索引值,所以能正常打印。
解决方案

方案1:将var替换为let

let是块级作用域,每次循环都会创建一个独立的i变量绑定,异步回调能捕获到当前迭代的i值:

const Users = require('pathToSchema')

const email = 'test@gmail.com'

Users.find()
  .then(async(result) => {
    // 把var改成let
    for (let i = 0; i < result.length; i++) {
      if (result[i].email == email) {
        console.log(result[i])
        Users.findById(result[i].id)
          .then((result2) => {
            // 现在能正常打印
            console.log(result[i])
          })
          .catch((err) => {
            console.log(err)
          })
      } else {
        if (i === result.length - 1) {
          console.log('email not found')
        }
      }
    }
  })
  .catch((err) => {
    console.log(err)
  })

方案2:提前保存当前用户对象

在循环里把当前的result[i]存到一个独立变量中,避免依赖i的变化:

const Users = require('pathToSchema')

const email = 'test@gmail.com'

Users.find()
  .then(async(result) => {
    for (var i = 0; i < result.length; i++) {
      // 保存当前用户到变量
      const currentUser = result[i]
      if (currentUser.email == email) {
        console.log(currentUser)
        Users.findById(currentUser.id)
          .then((result2) => {
            // 打印提前保存的变量
            console.log(currentUser)
          })
          .catch((err) => {
            console.log(err)
          })
      } else {
        if (i === result.length - 1) {
          console.log('email not found')
        }
      }
    }
  })
  .catch((err) => {
    console.log(err)
  })

方案3:优化查询逻辑(推荐)

你完全不需要先查询所有用户再遍历,直接用findOne根据邮箱查找目标用户,效率更高,也从根源避免了这个问题:

const Users = require('pathToSchema')

const email = 'test@gmail.com'

// 直接通过邮箱查找用户
Users.findOne({ email: email })
  .then((user) => {
    if (user) {
      console.log(user)
      // 如果确实需要再用id查询(其实没必要,findOne已经拿到完整对象了)
      Users.findById(user.id)
        .then((result2) => {
          console.log(user)
        })
        .catch((err) => {
          console.log(err)
        })
    } else {
      console.log('email not found')
    }
  })
  .catch((err) => {
    console.log(err)
  })

注:如果只是要验证邮箱存在并获取用户信息,findOne已经能直接拿到完整对象,不需要再调用findById,这一步是多余的,可以直接省略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:51:31