0

I have this async function that should be logging the returned database record after it is inserted. Instead, node tries to log the record before the async await function has returned the data from API.

fn: async function(inputs) {

  let companyId = await tg.getCompanyIdByEmail(inputs.orderData.email)
  let newCompany = {};
  if (!companyId) {
    newCompany = await tg.createCompany(inputs.orderData)
    sails.log('new company id: ' + newCompany.id) // this line being called before await finishes above and throwing undefined error
  }

  return;

},

This is the async function tg.createCompany()

async createCompany(orderData) {

  const companyType = orderData.business_name === "" ? 'consumer' : 'business';
  const companyName = companyType === 'consumer' ? `${orderData.first_name} ${orderData.last_name}` : orderData.company_name;

  let company = {
    company_type: companyType,
    name: companyName,
    email: orderData.email
  }

  request({
    method: 'POST',
    url: `${this.baseUrl}/companies/`,
    headers: this.headers,
    json: company
  }, (err, res, body) => {
    if (err) throw new Error('request error: ' + err);
    if (!body.company) throw new Error('API error: ' + body.message)
    sails.log('tg company created', body.company) //this is logging AFTER other function errors out as undefined
    return body.company;
  })
}

How do I get the function to wait for the async function to return the data?

chuckieDub
  • 1,767
  • 9
  • 27
  • 46
  • 2
    FYI, the `request()` library has been deprecated and one should generally not write new code using it. A list of alternatives is [here](https://github.com/request/request/issues/3143). One thing you will find in ALL the alternatives is promise support which you also need to solve your problem here. I'd suggest the [`got()` library](https://www.npmjs.com/package/got) in that list of alternatives (that's why I'm using and it has met my needs simply and completely and is fully based on promises which is how you should be writing asynchronous code these days). – jfriend00 May 27 '20 at 02:01
  • great, that seems like the issue here. thanks – chuckieDub May 27 '20 at 02:02
  • Plenty more explanation about how `await` needs to await a promise in order to do anything useful is in [the question yours is marked a duplicate of](https://stackoverflow.com/questions/62014830/my-async-wont-stop-for-my-await-what-does-await-wait-for-then). – jfriend00 May 27 '20 at 02:13

1 Answers1

1

createCompany needs to create a promise and return that. eg:

const createCompany = (orderData) => {
  return new Promise((resolve, reject) => {
    // ...
    // your existing code goes here.
    // Then inside the callback from request, call reject(err) on err,
    // and call resolve() when the result is good, i.e:
    // ...
    resolve(body.promise)
  })
}

now you can "await" on createCompany.

yen
  • 1,769
  • 2
  • 15
  • 43
  • Doesn't declaring a function as async automatically return a promise? – chuckieDub May 27 '20 at 01:53
  • Yes it should, but async/await is just syntactic sugar for regular promises so sometimes going back down to using bare promises clarifies where things are going wrong. My answer was very lazy; apologies. – yen May 27 '20 at 01:58
  • writing out the promise syntax worked but I'm going to leave this open for a while – chuckieDub May 27 '20 at 02:01
  • Hehe - cool! Maybe someone can come along and enlighten both of us! :-) – yen May 27 '20 at 02:02
  • 1
    @chuckieDub - FYI, one reason to not wrap your own promise around functions like this is that people often don't get the error handling correct and that's the case here. Missing from this example is the various ways that the `request()` library can communicate an error where this manually wrapped promise should `reject()`. Just use an http request library that already supports promises and you won't have this problem as I mentioned in my comment to the main question. – jfriend00 May 27 '20 at 02:11