【问题标题】:Inserting multiple results to req object in express.js route将多个结果插入到 express.js 路由中的 req 对象
【发布时间】:2017-03-10 14:03:02
【问题描述】:

我正在使用 ElasticSearch 运行 Express.js/Node.js 应用程序。我正在尝试查看同一索引中多种类型的结果。我在这里所做的是运行搜索查询并根据查询结果执行第二个搜索查询。通过观察 node.js 控制台,我也可以看到 elasticsearch 为玩家返回的结果。但它们没有插入到我的结果对象/数组中。我正在使用 express 中间件,因为我必须执行两个搜索并将结果显示为一个。

routes/index.js

function searchTeam(req, res, next){
  searchModuleTeams.searchTeams(req.body, function(data) {
    req.teams = data;
    next();
  });
}

function searchPlayer(req, res, next){
  //req.players = [];
  req.teams.forEach(function(team){
    req.body = {searchTerm:team._source.shortName};
    searchModulePlayers.searchPlayers(req.body, function(data){
      req.players.push(data);
      console.log(req.players);
    });
  });
  next();
}

function renderResults(req, res){
  res.render('index',{
    title:'Search Teams and Players',
    teams:req.teams,
    players:req.players
  });
}

router.post('/search-tp',searchTeam, searchPlayer, renderResults);

我通过阅读post1post2 提出了这个解决方案。我可以显示团队数组。但是没有任何东西来自玩家数组。我在这里做错了什么。

【问题讨论】:

  • searchPlayer()中,next()在你得到搜索结果之前被调用。
  • 正如@Aynoror 所说,您的下一个放置错误。除此之外,我认为使用多个中间件来收集数据并不是一个好方法。你试过aycnc图书馆吗?对于这个用例,它的 waterfall 方法很合适。
  • @Aynolor ,@Talha:我应该在哪里放置下一个()。我真的很想在渲染结果之前完成对 searchPlayer 的调用。同时我会寻找异步。

标签: javascript node.js express elasticsearch


【解决方案1】:

在你的searchPlayer 函数中,next() 调用应该放在searchPlayers() 调用的回调中,基本上就是你为searchTeam() 函数所做的。

function searchTeam(req, res, next){
  searchModuleTeams.searchTeams(req.body, function(data) {
    req.teams = data;
    next();
  });
}

function searchPlayer(req, res, next){
  req.players = [];                      <--- uncomment this...
  req.teams.forEach(function(team){
    req.body = {searchTerm:team._source.shortName};
    searchModulePlayers.searchPlayers(req.body, function(data){
      req.players.push(data);            <--- ...otherwise this will fail
      next();                            <--- move next() here
    });
  });
}

function renderResults(req, res){
  res.render('index',{
    title:'Search Teams and Players',
    teams:req.teams,
    players:req.players
  });
}

router.post('/search-tp',searchTeam, searchPlayer, renderResults);

正如 Talha Awan 所建议的,您最好不要在中间件中执行此操作,而是使用专用库,例如​​ async one(但还有很多其他库)

import waterfall from 'async/waterfall';

function searchTeam(callback){
  searchModuleTeams.searchTeams(req.body, function(teams) {
    callback(null, teams);
  });
}

function searchPlayer(teams, callback){
  let teamPlayers = [];
  async.each(teams, function(team, teamCallback) {
    let search = {searchTerm: team._source.shortName};
    searchModulePlayers.searchPlayers(search, function(players){
       teamPlayers.push(players);
       teamCallback();
    });
  }, function(err) {
    callback(err, teams, teamPlayers);
  });
}

function renderResults(req, res){
  async.waterfall([
    searchTeam,
    searchPlayer
  ], function (err, teams, players) {
    res.render('index',{
      title:'Search Teams and Players',
      teams: teams,
      players: players
    });
  });
}

router.post('/search-tp', renderResults);

【讨论】:

  • 感谢您的解释性回答。我都试过了。目前瀑布库不起作用,因为我无法找到将搜索参数传递给 searchTeam 的方法。无论如何考虑通过将 next() 放在循环中的第一个选项,我在访问 renderResults 中的玩家数组时遇到了麻烦。 player 应该是一个数组数组,其中每个数组都包含播放器对象。当只有一个球队可用时,球队数组包含一个项目,球员数组包含球队的一组球员。当返回一个以上的团队时,需要对其进行安排。
  • 绝对有可能bind 给定上下文异步函数(即this + 参数)。例如,async.waterfall([ searchTeam.bind(null, 42), searchPlayer ] 如果您想运行团队 id=42 的搜索
  • 我想我应该试试 async.waterfall。使用当前结构,当我有多个玩家对象推送到 req.players 时,我得到“发送后无法设置标题”。日志显示数据。但是由于调用了 next() 我认为它已经发送到 renderResults 并且无法在循环的后续迭代中使用更新的数据呈现结果。有没有其他方法可以正确迭代函数并在渲染它们之前获取所有结果。由于 js 的异步特性,我想我被困在这里了。
  • 问题是当你有多个团队并且req.teams.forEach() 会调用next() 几次,这不好。
  • 我想通了。然后我转向研究promise,express-promise-router。仍然没有运气。我主要关心的问题是当它有很多项目时处理 req.teams。我找到了一个使用items.map(fn) 类代码迭代数组项的方法。但仍在努力。
猜你喜欢
  • 2021-05-27
  • 1970-01-01
  • 2015-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
  • 2014-04-29
  • 2021-05-09
相关资源
最近更新 更多