Genko
Genko

Reputation: 345

Really confused with JS async (calling to 2 API)

So a simple explanation of what I am doing. First, I am accepting a GET request from an end user. Second, I am passing a (I am making a GET request now) parameter from the get request to an async function that returns a user's email address based on the parameter (essentially a vanity url. "Bob" vs "Robert Richardson").

Third, I am making on more GET request, to a second system, which returns a JSON file containing different tidbits about the user.

I know the callouts work normally because I can run node index.js with a function where I manually pass in the information I need, and it returns the desired results. But when I start my nodejs server, and try to respond to an incoming GET request (me testing, definitely not live) I get very weird results...

Here is simply what I am trying to get working at the moment: //server.js const express = require('express'); const bodyParser = require('body-parser'); const app = express(); const port = 8000;

app.use(bodyParser.urlencoded({
  extended: true
}));

require('./app/routes')(app, {});
app.listen(port, () => {
  console.log('test is listening on port :: ' + port);
});

//routes.js
const getdata = require('./getData '); //contains function for GET request one to convert param to email


async function getReturn(app, db) {
  app.get('/getDataFrom/:alias', (req, res) => {
    const alias = req.params.alias;
    console.log('alias : ' + alias);
    getEmailFromPromise(alias);

  });


}

async function getEmailFromPromise(alias) {
  console.log('getting email');
  let output = await getEmail(alias);
  console.log('output :: ' + output);
  // return output;
}

function getEmail() {
  return new Promise(resolve => {
    let email = getdata.getUserInfo(alias);
    resolve(email);
  }, 1000);
}

Worth noting, JS and Node are not what I commonly code it, but I need to for a project I am helping out with. I can get simple examples to work, but not my one making requests.

Passing in GET: localhost:8000/getDataFrom/bob

The above returns the following:

test is listening on port :: 8000
alias : rrichardson
getting email
output :: undefined   //I am wanting this to log after I actually get the email
email found :: [email protected]   //I do get this back, but out of order. The undefined above should also be this

The other file if it helps (it is exported properly):

//this is callout one getData 

async function getUserInfo(alias){
client.connect();
client.query('select email, firstname, lastname from salesforce.user WHERE 
alias = \''+ alias + '\'', (err, res) => {
if (err) console.log('err :: ' + err);
// console.log(res.rows);
   client.end();
   var email = res.rows[0].email;
   if(email != null){
     console.log('email found :: ' + email);
     return email;
    } 
    else return 'No Email Found';
  });
}

Obviously I left out my credentials, but the last js file DOES work just fine when I pass specific data into it. Again, just issues when trying to respond to a GET request that is incoming to me. I would really appreciate any help clearing this up. I am pretty sure I can get the second GET request figured out if I can get some help figuring out this first one.

Thanks!

Upvotes: 1

Views: 179

Answers (2)

Hector Martinez
Hector Martinez

Reputation: 427

you are mixing async and promises, it would be avoid. Your problem is th function getUserInfo is async but it has no "await" part, it is not waiting for "resolve" or return so it returns nothing or "undefined" because you ra anssigning that to the email in " let email = getdata.getUserInfo(alias);" you could use primse in this step, some like this:

function getUserInfo(alias){
    return new Promise(function(resolve, reject){
        client.connect();
        client.query('select email, firstname, lastname from salesforce.user WHERE alias = \''+ 
                 alias + '\'', (err, res) => {
            if (err) reject('err :: ' + err);
            // console.log(res.rows);
            client.end();
            var email = res.rows[0].email;
            if(email != null){
                console.log('email found :: ' + email);
                resolve(email);
            } 
            else reject('No Email Found');
        });
    }
}

and call it:

function getEmail() {
    return new Promise(resolve => {
        getdata.getUserInfo(alias).then(function(email){
            resolve(email);
        });
    });
}

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 371049

You need getReturn to return the promise generated by the getEmailFromPromise call. Because app.get uses a callback rather than a promise, you'll have to explicitly convert it to a promise first - in which case there's not much use in making getReturn async.

function getReturn(app, db) {
  return new Promise((resolve) => {
    app.get('/getDataFrom/:alias', (req, res) => {
      const alias = req.params.alias;
      console.log('alias : ' + alias);
      getEmailFromPromise(alias)
        .then(resolve);
    });
  });
}

The other problem is that getUserInfo also uses callbacks rather than promises - you can't just turn it into an async function, you'll have to explicitly convert it to return a Promise as well:

function getUserInfo(alias){
  return new Promise((resolve, reject) => {
    client.connect();
    client.query('select email, firstname, lastname from salesforce.user WHERE 
                 alias = \''+ alias + '\'', (err, res) => {
      if (err) {
        console.log('err :: ' + err);
        reject(err);
      }
      // console.log(res.rows);
      client.end();
      var email = res.rows[0].email;
      if(email != null){
        console.log('email found :: ' + email);
        resolve(email);
      } 
      else resolve('No Email Found');
    });
  });
}

You also need to use await to consume promises if you want the line below to run only after the promise has resolved:

function getEmail() {
  return new Promise(resolve => {
    let email = await getdata.getUserInfo(alias);

But it doesn't make much sense to await something that's a promise if you're just going to resolve it immediately. (and the second argument you provide to the promise in getEmail, 1000, doesn't make any sense)

Just return the promise itself:

function getEmail() {
  return getdata.getUserInfo(alias);
}

Upvotes: 1

Related Questions