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

Keystone.js中通过updatedBy实体获取用户信息问题求助

搞定你的KeystoneJS用户关联问题!

嘿,你遇到的这个问题其实是典型的异步操作执行顺序踩坑——你在forEach里调用的User.model.findById()是异步请求,而外层的next(err)根本不等这些请求完成就直接执行了,导致你在外部访问element.userDetails的时候,这些值还没来得及被赋值,自然就是undefined啦。

问题出在哪?

你原来的代码里,forEach循环发起一堆异步查询,但这些查询还没返回结果,你就直接调用next(err)结束了init钩子,这时候locals.data.posts里的userDetails还没被设置,外部自然拿不到值。

修复方案

我们可以用Promise.all()来统一等待所有用户查询完成,确保所有userDetails都赋值好之后再调用next。修改后的代码如下:

view.on('init', function (next) {
  var q = keystone.list('Post').paginate({
    page: req.query.page || 1,
    perPage: 5,
    //maxPages: 10,
    // filters: {
    //   state: 'published',
    // },
  })
  .sort('-publishedDate')
  .populate('author categories');

  if (locals.data.category) {
    q.where('categories').in([locals.data.category]);
  }

  q.exec(function (err, results) {
    if (err) return next(err); // 先处理文章查询的错误
    locals.data.posts = results;

    // 把每个用户查询转换成Promise,方便统一等待
    const userFetchPromises = locals.data.posts.results.map(post => {
      return User.model.findById(post.updatedBy).exec()
        .then(user => {
          // 给当前文章赋值用户详情
          post.userDetails = `Dr. ${user.name.first}${user.name.last}`;
          return post;
        });
    });

    // 等待所有用户查询完成
    Promise.all(userFetchPromises)
      .then(updatedPosts => {
        // 更新posts数组为已经赋值好用户详情的版本
        locals.data.posts.results = updatedPosts;
        next(); // 所有准备工作完成,继续下一步
      })
      .catch(fetchErr => {
        next(fetchErr); // 捕获用户查询中的错误并传递
      });
  });
});

核心改动说明

  • 把forEach换成map,将每个用户查询包装成Promise,这样就能用Promise.all()监听所有异步操作的完成状态
  • 只有当所有用户数据都查询完成、userDetails都赋值完毕后,才调用next(),确保外部访问时数据已经准备妥当
  • 完善了错误处理,不管是文章查询还是用户查询的错误,都能正确传递给Keystone的钩子处理

这样修改后,你再去访问locals.data.posts.results里的userDetails,就能拿到你想要的用户关联数据啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:53:50