0

I am trying to create a route that makes 2 API calls, the second depends on the results from the first one and only needs to be called if certain criteria are met. Below are the problems I am having.

  1. The finalCheck function seems to get called before the forEach no matter what? Even when wrapped in the if statement
  2. The counter and userNamesAvailable are not available out of the scope they are assigned in.
  3. I am sure there is a better way to do this and would love any relevant advice.

    router.post('/namecheck', async function(req, res, next) {   
      var name = req.body.name;
      var counter = 0
      var domains = []
      var userNamesAvailable = []
      var dotcom = true
      var answer = ''
    
    getDomains(checkDomains)
    
    // Check domain availabilty
    function getDomains (callback) {
      var url='https://api.ote-godaddy.com/v1/domains/available?checkType=FAST'
      Unirest.post(url)
        .headers({
          "Authorization" : "sso-key ",
          "Content-Type": "application/json"
        })
        .send(
          [
            name + '.com',
            name + '.net',
            name + '.org'
          ]
        )
        .end(function(response) { 
          domains=response.body.domains
          console.log(domains)
          callback(domains)
        })
    
    }
     function checkDomains(domains) {
       var d = 0
    
    //If no data is returned send error
    if(!domains) 
    {
      console.log("No data returned")
      return next("No data returned")
    } else {
      //Check how many domains are unavailable
      for(var i=0; i < domains.length; i++) {
        if(domains[i].available == false){
          d = d + 1
          //Flag if the .com is available
          if(domains[i].domain == name + '.com') {
            dotcom = false
          }
        }
      }
    
      if (d >2) {
        console.log("d is greater than 1")
        answer = 'no'
      //If 2 domains are available and one is .com continue
      } else if (d>1 && dotcom =='false') {
        answer = 'no'
      }
    }
    getUsernames(finalCheck)
    }
    
    function getUsernames(callback){
      // Social Sites to Check
      var sitenames = [ 
        'facebook',
        'twitter',
        'instagram',
        'youtube',
        'slack',
        'blogger'
      ]
    
      // Check Usename availabitliy
      let i = 0
      sitenames.forEach(sitename => {
    
      Unirest.post('https://api.namechk.com/services/check.json')
      .headers({
        'AUTHORIZATION': 'Bearer ',
        'Accept': 'application/vnd.api.v1+json',
      }).send({
        'site': sitename, username: name,
      }).end(function(response) { 
        if(response.body.available == false){
          counter ++
        } else {
          userNamesAvailable.push(response.body)
        }
      });
      i++
    });
    console.log(counter)
    console.log(userNamesAvailable)
    if(i == sitenames.length){
      callback(counter, dotcom)
     }
    }
    
    function finalCheck(counter, dotcom) {
      console.log('Start finalCheck')
      console.log(counter)
      console.log(dotcom)
        //Final Check for is a name is a go or not
        //If one social site is not available and the 
        if(counter == 1 && dotcom =='true') {
          console.log(5-counter + ' social sites available')
          res.send("yes");
        } else {
          res.send("no")
        }
      }
     })
    
3
  • I don't know if this is the issue but you have d > 1 & dotcom == 'false' and perhaps you meant d > 1 && dotcom == false (ie, change & to && and change 'false' to false). Same changes for finalCheck. Commented Oct 30, 2018 at 21:02
  • the callback on getUsernames happens before the forEach because each of those elements creates an asyncronous call. You need to watch that all of those requests end before calling the callback. Commented Oct 30, 2018 at 21:06
  • Thanks I did catch that conditional but it is not affecting the other code. I realize why the getUsernames getting called but not sure how to structure it correctly. Commented Oct 30, 2018 at 21:16

1 Answer 1

3

Following the answer on this question. You should be able to do it using Promise.

You have to change only the function getUsernames.

  function getUsernames(callback) {
    // Social Sites to Check
    var sitenames = [
      'facebook',
      'twitter',
      'instagram',
      'youtube',
      'slack',
      'blogger'
    ];

    // Check Usename availabitliy
    let requests = sitenames.map((sitename) => {
      return new Promise((resolve) => {
        Unirest.post('https://api.namechk.com/services/check.json')
          .headers({
            'AUTHORIZATION': 'Bearer ',
            'Accept': 'application/vnd.api.v1+json',
          }).send({
            'site': sitename,
            username: name,
          }).end(function(response) {
            if (response.body.available == false){
              counter++;
            } else {
              userNamesAvailable.push(response.body);
            }
            resolve();
          });
      });  
    });

    Promise.all(requests).then(() => { 
      console.log(userNamesAvailable);
      callback(counter, dotcom);
    });
  }

  function finalCheck() {
    console.log('Start finalCheck')
    console.log(counter)
    console.log(dotcom)
    //Final Check for is a name is a go or not
    //If one social site is not available and the
    if (counter == 1 & dotcom == 'true') {
      console.log(5 - counter + ' social sites available')
      res.send("yes");
    } else {
      res.send("no")
    }
  }

Remember that asyncronous functions in javascript are a feature and not something you should be fighting (what I think you are trying to do declaring your main function as async function). Try to understand them first and you will notice they are a big advantage.

There is plenty of documentation about them out there... async Fucntion understanding Promises

EDIT: Do not send the variables that you call global as parameters, they are already available in the called function.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks! So I am still wondering why the userNamesAvailable and counter are not available globally? Everything else seems to be working.
I will edit my answer to handle your logs of userNamesAvailable and increment the counter on each Unirest.end, you should see the logs working correctly.
That would work also, I am actually counting the false responses and saving the true ones. I had my code as above but counter and userNamesAvailable are still not available.
How do you know they are not available?
The console.log for userNamesAvailable is always [] except inside the loop
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.