【问题标题】:Trouble initiating background process in node.js在 node.js 中启动后台进程时遇到问题
【发布时间】:2019-06-12 03:37:14
【问题描述】:

我有一个带有以下代码的 node.js/express 设置。客户端代码是用 React 构建的。他们能够使用从 1 到任何他们想要的任何东西来查询 X 数量的玩家。查询被发送到我的快速服务器,该服务器向 Riot Games 公共 API 发送请求。我遇到的问题是,如果查询太大,则获取超时。

有人给了我一个想法,让初始 POST 请求返回一个“id”,然后在后台运行实际查询。然后让客户端的浏览器定期检查查询是否通过 GET 请求完成。

我在 React componentDidMount() 中调用初始 POST,然后在 componentDidUpdate() 中发送 GET 请求。我认为我在发送获取请求时搞砸的地方以及我如何启动后台进程。我将查询结果推送到 allResults[0] 数组。 playerRequest 是一个异步函数。

希望我解释得足够好......不太确定该怎么做。

src/server/index.js

var playerSearch = require('./playerSearch.js');
const express = require('express');
const bodyParser = require('body-parser');
const uuidv1 = require('uuid/v1');

const app = express();
app.use(express.static('dist'));
app.use(bodyParser.json());
app.use(express.json());

const port = process.env.PORT || 8080;
app.listen(port, () => console.log('Listening on port ' + port + '!'));

var allResults = [];

//Beginning of all methods
app.get('/api/getUsername', (req, res) => res.send({ username: 'Summoner' }));

app.post('/api/champstats/initiatePlayerSearch', async function(req, res){
  var searchID = uuidv1();
  allResults.push(await playerSearch(req, searchID));
  console.log('Search ID: ' + searchID);
  return res.send({searchID: searchID});
});

app.get('/api/champstats/playerSearch/:searchId', async function(req, res){
  const result = await allResults.filter(x => x.requestID === req.params.searchID);
  return res.send({stats: result[0].stats});
});

【问题讨论】:

  • 删除 awaitplayerSearch 是否修复它? (好吧,帖子部分,至少...... get 需要更改......)
  • 另外,将 allResults 设为对象或地图,而不是推送,将来自 'playerSearch' 的承诺放在 searchID 键下,这样您就可以在 get...
  • 感谢您的回复。不幸的是,删除 await 不起作用。我的浏览器仍然超时并出现以下错误:“net::ERR_EMPTY_RESPONSE,错误:TypeError:无法获取”。我也确实将 allResults 放入了一个对象中。我一开始就应该这样做。
  • 失败来自/api/champstats/initiatePlayerSearch 请求? (/api/champstats/playerSearch/:searchId 仍然可以按照当前的编写方式超时)
  • 当前失败来自/api/champstats/playerSearch/:searchId (GET) 请求。我想也许我需要定期调用这个请求,直到它成功(或失败),但我不知道该怎么做。现在我在/api/champstats/initiatePlayerSearch 返回searchID 后立即调用它。 searchID 更新我的 React 组件状态,它调用 componentDidUpdatecomponentDidUpdate 里面是我的 GET 请求,它只被调用一次。此请求超时,因为 playerSearch(req) 仍在处理数据。

标签: javascript node.js reactjs express asynchronous


【解决方案1】:

等待异步结果端点中的承诺,但如果尚未获取结果,也会超时:

var playerSearch = require('./playerSearch.js');
const express = require('express');
const bodyParser = require('body-parser');
const uuidv1 = require('uuid/v1');

const {promisify} = require('util');

const app = express();
app.use(express.static('dist'));
app.use(bodyParser.json());
app.use(express.json());

const port = process.env.PORT || 8080;
app.listen(port, () => console.log('Listening on port ' + port + '!'));

var allResults = {};

const timeout = promisify(setTimeout);

//Beginning of all methods
app.get('/api/getUsername', (req, res) => res.send({ username: 'Summoner' }));

app.post('/api/champstats/initiatePlayerSearch', async function(req, res){
  var searchID = uuidv1();
  allResults[searchID] = playerSearch(req, searchID);
  console.log('Search ID: ' + searchID);
  return res.send({searchID: searchID});
});

app.get('/api/champstats/playerSearch/:searchId', async function(req, res){
  const searchResult = allResults[req.params.searchID];
  const result = await Promise.race([ // return the first result you get
    timeout(100).then(async ()=>null), // wait for 100ms then return null.
    searchResult # if the search result returns before 100ms, use that as the result
    ]);
  if (result != null){
    return res.send({stats: result[0].stats});
  } else {
    // return an error message so you can try again later
  }
});

如果您想试验一下,可以使用 async await 而不是使用.then 来执行此模式的几种变体。不过需要注意的一点是,任何超时回调都可能不响应请求,因为如果另一个承诺首先返回,它不会被取消。传递给.race 的所有承诺最终都会完成,所以如果你在res 上调用方法,请记住这一点。 .race 不会取消待处理的承诺。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-25
    • 2018-07-19
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    相关资源
    最近更新 更多