Javascript 递归Steam API调用未终止

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

我使用axios和Node.js中的promises,通过Steam的web API为其中一款游戏调用API端点。来自端点的每个JSON响应返回100个匹配对象,其中只有大约10到40个(平均)是我的用例感兴趣的。此外,我观察到,如果在一秒钟内多次调用,数据往往会重复。 我试图实现的是通过连续(递归)调用api,在数组中获得100个符合我的条件的
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);
  }
}