javascriptaxioses6-promisetomtom

Promises and Axios request still returns 429 despite setTimeout


I've been having a problem with the Reverse Geocode API provided by TomTom where I get 429 responses back, because I am mapping over 72 latitude and longitude objects to the API.

So I decided tried to make a function which would wait 5 seconds before firing another request; As TomTom advises 5 seconds between requests.

I thought it was totally kosher to (like in my function below) call a function, (like in my case) call Topography.getTopography(latLng) and then off of that then call, I can take that result and feed it to the TomTom request. Is this wrong? Or is it my setTimeout?

Here is my function

async function getTopographyData(latLang) {
    const retryTimes = 5;
    let counter = 0;
    var newObj = {};

    Topography.getTopography(latLang, options)
      .then((results) => {
        newObj.topography = results;
        newObj.latlng = latLang;
        return newObj;
      })
      .then(async (newObj) => {
        var { lat, lng } = newObj.latlng;

        let result = await axios.get(
          `https://api.tomtom.com/search/2/reverseGeocode/crossStreet/${lat},${lng}.json?limit=1&spatialKeys=false&radius=10000&allowFreeformNewLine=false&view=Unified&key=${process.env.TOM_TOM_API}`
        );

        var { addresses } = result?.data;
        var { address, position } = addresses[0];

        var [lat, lng] = position.split(",").map((p) => +p);

        newObj = {
          ...newObj,
          latlng: { lat, lng },
          address,
        };

        dispatch({ type: "setTopographyData", payload: newObj });
      })
      .catch(function (error) {
        if (
          (error.response?.status == 403 || error.response?.status == 429) &&
          counter < retryTimes
        ) {
          counter++;
          return new Promise(function (resolve, reject) {
            setTimeout(function () {
              resolve(getTopographyData(counter));
            }, 5000);
          });
        } else {
          console.log("error", error);
        }
      });
  }

Any help would be appreciated.

Update while num8er's solution works, I believe there must be a problem with TomTom as it stops at 45 (getting a reverseGeoCode look up for 45 markers latlang objects) and spits back errors in the console. Furthermore when I click the link in the console I can see the response in the browser?!

enter image description here

enter image description here


Solution

  • How about refactoring it with regular loop with pause and break to make code more readable:

    async function getTopographyData(latLng) {
        const retryTimes = 5;
        const topographyData = {
          latlng: latLng,
          address: null,
        };
    
        const pause = (ms) => new Promise(resolve => setTimeout(resolve, ms));
    
        for (let counter = 1, canRetry = false; counter <= retryTimes; counter++) {
          try {
            const topography = await Topography.getTopography(latLng, options);
            topographyData.topography = topography;
           
            const { lat, lng } = topographyData.latlng;
            const response = await axios.get(
              `https://api.tomtom.com/search/2/reverseGeocode/crossStreet/${lat},${lng}.json?limit=1&spatialKeys=false&radius=10000&allowFreeformNewLine=false&view=Unified&key=${process.env.TOM_TOM_API}`
            );
            
            if (response?.data) {
              const { addresses } = response.data;
              const { address, position } = addresses[0];
              
              const [lat, lng] = position.split(",").map((p) => +p);
              
              topographyData.address = address;
              topographyData.latlng = {lat, lng};
            }
            
            dispatch({ type: "setTopographyData", payload: topographyData });
          }
          catch (error) {
            console.error(error);
            
            canRetry = [403, 429].includes(error.response?.status);
          }
          
          if (!canRetry) {
            break;
          }
          
          await pause(5000);      
        }
      }