0

I want to access some data from an API and ran into a problem. My code is fetching some data from the API, will compare it with a local copy of an API. I want it to store some data in an array if the local copy does not match the copy fetched from the API. The fetching and comparison is working fine. The problem comes up when I try to fill the array and want to give it back. The request function is async so my return value at the end will be undefined. My function checkForDiff should return this array after the for-loop is done, because after the foor-loop the array should be filled with the information I need. I am a newbie in Nodejs so I really do not know how to fix it. I need the array to be filled before returning it, but the async request call is causing me problems. How can I achieve this kind of behavior? Thank you for your help in advance

function checkForDiff(){
 let outdatedLanguages = [];

 var options = {
   url: 'https://xxxxxxxxxxxxxxxxxxxxxxxxx',
   headers: {'Key': 'xxxxxxxxxxxxxxxxxxxxxx'}
 };
 for(let index = 0; index < locales.length; index++){
    //Change url for new https request
    options.url = `https://xxxxxxx?locale=${locales[index].symbol}`
    //Send new https request to API
    request(options, (error, response, body)=>{
       var localState = hash(JSON.parse(filesystem.readFileSync(`./cards/cards-${locales[index].symbol}.json`)));
       var recentState = hash(JSON.parse(body));
       /If the local card base is not up to date, add locale to array
       if(localState !== recentState){
        outdatedLanguages.push(locales[index].symbol);
       }
    );
  }
 //Return outdatedLanguages array
 return outdatedLanguages;
}
r3ngE
  • 13
  • 2
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – caffeinated.tech Nov 29 '18 at 13:45

1 Answers1

0

To get the correct data, you need to use promises. Instead of request callback, use promise.

Because checkForDiff() is an async function, you should return a promise from the function instead of trying to return the outdatedLanguages. For your case, you need to use Promise.all() function because you have multiple async functions. In a sense, Promise.all() waits for all tasks to accomplish. In the other part of the code where you use that function, you should be aware that the function is a promise so you should use it accordingly. Basically, you can do something like this.

function checkForDiff() {

    let outdatedLanguages = [];
    let promises = [];

    var options = {
        url: 'https://xxxxxxxxxxxxxxxxxxxxxxxxx',
        headers: { 'Key': 'xxxxxxxxxxxxxxxxxxxxxx' }
    };
    for (let index = 0; index < locales.length; index++) {
        //Change url for new https request
        options.url = `https://xxxxxxx?locale=${locales[index].symbol}`

        promises.push(/* request as promise */);
    }

    return Promise.all(promises).then(() => outdatedLanguages);

}

You call the function like this.

checkForDiff().then((outdatedLanguages) => {
    // outdatedLanguages is the array you want
})

For request promise you can use request-promise package. Use the command npm install --save request-promise. Then include the package var rp = require('request-promise');. An example request is as following:

var options = {
    uri: 'https://api.github.com/user/repos',
    qs: {
        access_token: 'xxxxx xxxxx' // -> uri + '?access_token=xxxxx%20xxxxx'
    },
    headers: {
        'User-Agent': 'Request-Promise'
    },
    json: true // Automatically parses the JSON string in the response
};

rp(options)
    .then(function (repos) {
        console.log('User has %d repos', repos.length);
    })
    .catch(function (err) {
        // API call failed...
    });
Burak Gavas
  • 1,304
  • 1
  • 9
  • 11