duplicate sent requests inside nodejs loop

722 Views Asked by At

I am writing a program that can send multiple get requests to an external API using a loop (sending a request for each id ) but when I run the code I get duplicate json responses , for example in the code I have only 3 ids so the server should send one request per ids,that means 3 requests,but the problem is the server sends more than 3 requests even though the loop should stop at 3 requests,and with different order sometimes (without respcting the loop index ) please help I am so confused

    router.get('/activities/:stravaId',limiter,(req, res,done) => {

    const userc=req.user;
    const access_token=userc.access_token;

    var _=require("underscore");
    var fs=require("fs");
    const ids=[ 3822613688,3822608735,3822619781]
    strava = new stravaApi.client(access_token);
    for (const ind in ids) {
       strava.activities.listLaps({ id:ids[ind]},async function (err, payload) {
            if (!err) {
               console.log(payload)
               fs.appendFile("streamjson.json", JSON.stringify(payload), err => {
                    if (err) throw err;
                    console.log("Done writing"); // Success
                });
            } else {
                console.log(err)
            }
        })
    }
})
1

There are 1 best solutions below

2
On

I'm not sure what is causing your problem but I might be able to help you.

First I would recommend you to move the imports to the top of the module. I don't think you want to load "fs" and "underscore" with every new request.

Now about order. The callback function of listMaps will be executed when the request ends and it is its turn in the javascript event loop and this may take time.

For more details, we recommend you to read


const _ = require('underscore')
const fs = require('fs')

router.get('/activities/:stravaId', limiter, async (req, res, done) => {
  const { user } = req.user
  const { access_token } = user
  const ids = [3822613688, 3822608735, 3822619781]

  strava = new stravaApi.client(access_token)

  try {
    const results = await Promise.all(
      ids.map((id) => doWhateverStravaDoes(id, strava))
      //.map((p) => p.catch((e) => e)) you can do this in case you also want to receive errors
    )
    // now you have the results in order as an array
    console.log({ results })

    try {
      results.forEach(({ payload }) => appendToFile('streamjson.json', payload))
      // just remember that you cannot use .forEach with asynchronous functions
    } catch (error) {
      console.log(error)
    }
  } catch (error) {
    console.log({ error })
  }
})

function appendToFile(file, payload) {
  fs.appendFile(file, JSON.stringify(payload), (err) => {
    if (err) throw err
    console.log('Done writing') // Success
  })
}

function doWhateverStravaDoes(id, strava) {
  return new Promise((resolve, reject) => {
    strava.activities.listLaps({ id }, (err, payload) => {
      if (err) {
        reject({ id, err })
      } else {
        resolve({ id, payload })
      }
    })
  })
}