'await' is not working in async function

The code below gives me the following error:

SyntaxError: await is only valid in async function

async function getLastTransaction() 
{
    paymentsApi.listPayments(locationId, opts).then(function(transactions) 
    {
        if(transactions[transactions.length-1] === undefined)
            return; //no new transaction yet

        var last_transaction_id = transactions[transactions.length-1].id;
        var last_transaction_in_queue; 

        try {
            last_transaction_in_queue = JSON.parse(order_queue[0]).order_id;
        } catch (e) {
            last_transaction_in_queue = order_queue[0].order_id;
        }

        //check if latest transaction is the same as lastest transaction in queue
        if(last_transaction_id !== last_transaction_in_queue) {

            console.log(`new payment...`); 

            var obj = await createTransactionObject(transactions[transactions.length-1], () => {
                order_queue.unshift(obj);
                console.log('new added', order_queue);
            });
}

I don't understand the error since I'm using await for the same function createTransactionObject() but in another piece of code.

For example, in the following code, I don't get the error, and still, I'm using await before createTransactionObject()

async function populateQueue(transaction_list)  {
    for(var i = 0; i < transaction_list.length; i++) 
    {
        var transaction_json = await createTransactionObject(transaction_list[i], () => {});
        order_queue.unshift(transaction_json);
    } }

4 answers

  • answered 2018-04-14 15:58 psrcek

    You need to change this line:

    paymentsApi.listPayments(locationId, opts).then(function(transactions)
    

    to this:

    paymentsApi.listPayments(locationId, opts).then(async (transactions) =>
    

    The anonymous function you supply to .then needs to be asynced, because you're using await in it.

    You could also replace the line with this (maybe even better):

    const transactions = await paymentsApi.listPayments(locationId, opts);
    

    Because the getLastTransaction function is asynced.

  • answered 2018-04-14 16:06 16kb

    paymentsApi.listPayments(locationId, opts).then(function(transactions) should be paymentsApi.listPayments(locationId, opts).then(async function(transactions) as await can only be used in an asynchronous function.

    Better still, since you already have an async function at the top level, why don't you just await paymentsApi.listPayments(locationId, opts) instead of chaining it with a then?

    async function getLastTransaction() {
        const transactions = await paymentsApi.listPayments(locationId, opts);
        // Do something with transactions
    }
    

  • answered 2018-04-14 16:07 freakish

    First of all you get the error not because the getLastTransaction function is async but because the anonymous function .then(function(transactions) is not async and you use await inside of it. You can't do that.

    Now note that simple redeclaring the function as async function(transactions) will be syntactically correct but will that work fine? What happens now is that getLastTransaction fires some async process in the background and never awaits the result. Is that what you want?

    To fix that you have to ask yourself: what am I trying to achieve? Should getLastTransaction wait for whatever the inner function is doing? Then make use of that async declaration:

    async function getLastTransaction() {
        const transactions = await paymentsApi.listPayments(locationId, opts);
        // Some other code here
        return xyz;
    }
    

    This is under the assumption that the paymentsApi is async/await compatible. If it is not then you have to play with manually creating and returning Promise objects (in which case async declaration won't help much).

  • answered 2018-04-14 16:12 Zeeshan Hassan Memon

    await keyword works when scope is having async keyword used, here .then accepts callback function that doesn't have async, so await becomes alien here.

    Lets re-write your code in async-await style:

    async function getLastTransaction() 
    {
        // #1 this fixes to adopt the await style and fixes the problem
        const transactions = await paymentsApi.listPayments(locationId, opts);
    
        // your rest code goes here ...
    
        if(last_transaction_id !== last_transaction_in_queue) {
                //now do it like this, await will make sense now
                const obj = await createTransactionObject(transactions[transactions.length-1]);
                order_queue.unshift(obj);
        }
    }