0
votes

I'm unable to use async/await inside a 'new Promise' block which throws await is only valid in async function error. I don't know if it's even possible but I need to use it or a way to achieve what I want. Here's what I'm trying to do:

A user types in a query and it goes through a recursive function called doesExist. I have to use a recursive function because the API doesn't always provide data for a query. The recursive function will try 3 times, that is, it will send 3 api requests for the data before returning an error saying 'data couldn't be fetched'. In the function, I return a new promise as I have to make api requests from there.

To fetch data, I used request before but I want to use axios now with async/await. So how can I use axios with async/await inside a new Promise block?

This is the code with request:

router.get('/example', async (req, res) => {

        try{
            const query = 'Superman';
            const data  = await doesExist(query);
    
            if(!data) {
                console.log('No data');
            }
    
            res.render('../views/example', { data, query });
        }catch(err) {
            console.log(err);
        }
        
});
    
    
const doesExist = (query, retries = 0) => {

        const url           = `http://api.example.com/json?fields=${query}`;
        const maxRetries    = 3;
    
        return new Promise(( resolve, reject ) => {
            
            const retry = () => {
                if (retries < maxRetries) {
                    resolve(doesExist(query, retries + 1));
                } else {
                    reject(`Could not get the data after ${retries} retries.`);
                }
            };
    
            request(url, function (error, response, body) {
                if (!error && response.statusCode === 200) {
                    const data = JSON.parse(body);
                    resolve(data);
                } else {
                    retry();
                }
            });
       });
}; 

And this is what I tried with async/await which throws the error:

const doesExist = async (query, retries = 0) => {

        const url           = `http://api.example.com/json?fields=${query}`;
        const maxRetries    = 3;
    
        return new Promise(( resolve, reject ) => {
            
            const retry = () => {
                if (retries < maxRetries) {
                    resolve(doesExist(query, retries + 1));
                } else {
                    reject(`Could not get the data after ${retries} retries.`);
                }
            };

            const data = await axios.get(url);

            if(data.statusCode === 200) {
                resolve(data);
            }else{
                retry();
            }
     
       });
}; 

If it's not possible to use async/await inside promise block then please show me how I can achieve it. Thanks

2
Did you try new Promise(async ( resolve, reject ) => {?Anatoly
@Anatoly No, I just did. And it seemed to be working. Thanks a lot. Post it as an answer.Zak

2 Answers

1
votes

Never pass an async function as the executor to new Promise! If you want to use async/await and axios which already does return a promise, you don't need - and shouldn't use - the Promise constructor to promisify a callback API. Just write

async function doesExist(query, retries = 0) {
    const url           = `http://api.example.com/json?fields=${query}`;
    const maxRetries    = 3;

    const data = await axios.get(url);

    if (data.statusCode === 200) {
       return data;
    } else if (retries < maxRetries) {
       return doesExist(query, retries + 1);
    } else {
       throw new Error(`Could not get the data after ${retries} retries.`);
    }
}
-1
votes

The function the promise calls needs to be an "async" function like so.

new Promise (async (Resolve) => {
    await new Promise (async (_Resolve) => {
         console.log ("A");
         _Resolve ();
    });

    console.log ("B");
    Resolve ();
});