boing
boing

Reputation: 539

Nodejs variable undefined after "await"

I know there are questions like this already. I promise I've read them; I'm just not getting it. I have some simple code to get a token for a 3rd-party API service:

let tok = '';
const getToken = async () => {
  tok = await btt.get();
  console.log(tok);
};
getToken();

tok is always undefined at the console.log. I thought the whole point of await was that your code would pause until that particular promise was resolved or rejected; am I mistaken? Here's the get function:

async get () {
  this.paymentGateway.clientToken.generate({
    customerId: '5cdc7405da53494ee0f3bafe'
  }, (err, result) => {
    return new Promise((resolve, reject) => {
      if (result.success) {
        resolve(result.clientToken);
      } else {
        reject(result.errors);
      }
    });
  });
}

I've been stuck this particular issue for a while and tried a lot of different ways. If someone could help, I'd be grateful.

Thanks.

Upvotes: 3

Views: 1988

Answers (3)

Zlatko
Zlatko

Reputation: 19569

Your async function is not returning a promise. Try this:

async get () {
  return new Promise((resolve, reject) => {
    this.paymentGateway.clientToken.generate({
      customerId: '5cdc7405da53494ee0f3bafe'
    }, (err, result) => {
      if (result.success) {
        resolve(result.clientToken);
      } else {
        reject(result.errors);
      }
    }
  });
}

An example:

const mockPaymentGateway = {
  clientToken: {
    // a mock that will randomly succeed and fail.
    generate: (_, callback) => callback(null, Math.random() > 0.5 ? {
      success: true,
      clientToken: '<This is a token value.>'
    } : {
      errors: ['We have no moneys.']
    }),
  }
}

// I assume you have other things in your service, but here is an example
class SomeService {
  constructor(paymentGateway) {
    this.paymentGateway = paymentGateway;
  }


  async get() {
    return new Promise((resolve, reject) => {
      this.paymentGateway.clientToken.generate({
        customerId: '5cdc7405da53494ee0f3bafe'
      }, (err, result) => {
        if (result.success) {
          resolve(result.clientToken);
        } else {
          reject(result.errors);
        }
      });
    });
  }
}
// Generating mock data...

const btt = new SomeService(mockPaymentGateway);

let tok = '';
const getToken = async() => {
  try {
    tok = await btt.get();
    console.log(tok);
  } catch (e) {
    console.log('Errors getting token:', e);
  }
};

document.querySelector('#get-token').addEventListener('click', async() => {
  console.log('Getting token');
  getToken()
});
<button id="get-token">Get token</button>

Upvotes: 5

Hardik Shah
Hardik Shah

Reputation: 4200

Wrap your call inside Promise:

async get () {
  return new Promise((resolve, reject) => {
    this.paymentGateway.clientToken.generate({
      customerId: '5cdc7405da53494ee0f3bafe'
    }, (err, result) => {
      if (result.success) {
        resolve(result.clientToken);
      } else {
        reject(result.errors);
      }
    });
  });
}

Upvotes: 2

Jason Livesay
Jason Livesay

Reputation: 6377

You never resolved the promise. Change the last line to this:

getToken().catch(console.error);

Upvotes: 0

Related Questions