Javascript 递归Steam API调用未终止
我使用axios和Node.js中的promises,通过Steam的web API为其中一款游戏调用API端点。来自端点的每个JSON响应返回100个匹配对象,其中只有大约10到40个(平均)是我的用例感兴趣的。此外,我观察到,如果在一秒钟内多次调用,数据往往会重复。 我试图实现的是通过连续(递归)调用api,在数组中获得100个符合我的条件的Javascript 递归Steam API调用未终止,javascript,recursion,promise,axios,steam-web-api,Javascript,Recursion,Promise,Axios,Steam Web Api,我使用axios和Node.js中的promises,通过Steam的web API为其中一款游戏调用API端点。来自端点的每个JSON响应返回100个匹配对象,其中只有大约10到40个(平均)是我的用例感兴趣的。此外,我观察到,如果在一秒钟内多次调用,数据往往会重复。 我试图实现的是通过连续(递归)调用api,在数组中获得100个符合我的条件的match_ids(而不是整个match对象),直到获得100个唯一的match_ids满足我的目的 我知道在循环中调用端点是幼稚的,它超过了web a
match_id
s(而不是整个match对象),直到获得100个唯一的match_id
s满足我的目的
我知道在循环中调用端点是幼稚的,它超过了web api设置的每秒1个请求的调用限制。这就是为什么我求助于递归来确保每个承诺都得到解决,并在继续之前用match\u id
s填充数组。我遇到的问题是,我的代码没有终止,在递归调用的每个阶段,值都是相同的(例如,最后一个匹配id、实际构建的数组等)
我没有超过请求限制,但同样的结果不断出现
BATCH\u SIZE
为100
且
\u matchIds=[]
我首先要替换行:
matchesArray=[…新集合([…matchesArray,…filteredMatches])代码>
关于这一点:
filteredMatches.filter(项=>matchesArray.indexOf(项)==-1)。forEach(项=>{
匹配阵列推送(项目)
})
您所做的是用新引用有效地替换了函数中的matchesArray变量。我的意思是,您从外部发送到函数参数中的变量不再是函数内部的同一个变量。如果您使用matchesArray.push,那么您不会更改var引用,并且外部范围中的var会准确更新,正如您的意图一样
这就是为什么\u matcheids
保持为空的原因:每次调用makeRequestV2时,内部变量matchesArray
都会与外部范围“脱离”(在赋值语句执行期间),尽管它被填充,外部作用域变量仍然指向原始引用,并且保持不变。我将从替换行开始:
matchesArray=[…新集合([…matchesArray,…filteredMatches])代码>
关于这一点:
filteredMatches.filter(项=>matchesArray.indexOf(项)==-1)。forEach(项=>{
匹配阵列推送(项目)
})
您所做的是用新引用有效地替换了函数中的matchesArray变量。我的意思是,您从外部发送到函数参数中的变量不再是函数内部的同一个变量。如果您使用matchesArray.push,那么您不会更改var引用,并且外部范围中的var会准确更新,正如您的意图一样
这就是为什么\u matcheids
保持为空的原因:每次调用makeRequestV2时,内部变量matchesArray
都会与外部范围“脱离”(在赋值语句执行期间),尽管它被填充,外部作用域变量仍然指向原始引用,并且保持不变。您需要返回承诺,返回steamapi.getRawMatches(lastId)…
和返回makeRequestV2(matchesArray,lastIdFetched)代码>@thefourtheye我已经试着退了,但还是得到了同样的东西。有没有更好的方法来实现这一点?我很乐意接受建议。长话短说,我只是重复调用api(保持在速率限制内),然后在达到我想要的100项时停止。您需要返回承诺,返回steamapi.getRawMatches(lastId).
和返回makeRequestV2(matchesArray,lastIdFetched)代码>@thefourtheye我已经试着退了,但还是得到了同样的东西。有没有更好的方法来实现这一点?我很乐意接受建议。长话短说,我只是重复调用api(同时保持在速率限制内),然后在达到100个我想要的项目时停止。感谢您的回复。我很快会试试的。现在,我已经求助于使用node cron来实现调用之间的一些设置间隔,目前它对我来说运行正常。感谢您的回复。我很快会试试的。现在,我已经求助于使用节点cron来实现一些设置的调用间隔,目前它对我来说还可以。
function makeRequestV2(matchesArray, lastId) {
// base case
if (matchesArray.length >= BATCH_SIZE) {
console.log(matchesArray);
return;
}
steamapi
.getRawMatches(lastId)
.then(response => {
const matches = response.data.result.matches;
// get the last id of fetched chunk (before filter)
const lastIdFetched = matches[matches.length - 1].match_id;
console.log(`The last Id fetched: ${lastIdFetched}`);
let filteredMatches = matches
.filter(m => m.lobby_type === 7)
.map(x => x.match_id);
// removing potential dups
matchesArray = [...new Set([...matchesArray, ...filteredMatches])];
// recursive api call
makeRequestV2(matchesArray, lastIdFetched);
})
.catch(error => {
console.log(
"HTTP " + error.response.status + ": " + error.response.statusText
);
});
}
makeRequestV2(_matchIds);
// this function lies in a different file where the axios call happens
module.exports = {
getRawMatches: function(matchIdBefore) {
console.log("getRawMatches() executing.");
let getURL = `${url}${config.ENDPOINTS.GetMatchHistory}/v1`;
let parameters = {
params: {
key: `${config.API_KEY}`,
min_players: `${initialConfig.min_players}`,
skill: `${initialConfig.skill}`
}
};
if (matchIdBefore) {
parameters.start_at_match_id = `${matchIdBefore}`;
}
console.log(`GET: ${getURL}`);
return axios.get(getURL, parameters);
}
}