0

I'm doing a recursive request with async/await whenever the received response has length === 0. The problem is that when some request returns the desired data, the resolve(data); part of the promise doesn't seem to work.

So, in my code, I have reached the point where I get to make multiple recursive calls and, finally, receive a response whose length is not 0.

Note: there are plenty of API keys published in Github if you want to test the code.

var apiKey = "yourApiKey";
var url = "https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=";

function requestData(url) {
    return fetch(url).then(response => {
        if(response.ok) {
            return response.json().then(data => {
                return Promise.resolve(data);
            });
        } else {
            return Promise.reject(response.status);
        }
    });
}

function NasaRequest(sun, limit, frecuency) {
    return new Promise(async (resolve, reject) => {
        var data = await requestData(url + sun + "&api_key=" + apiKey);
        if(data.photos.length === 0 && !limit) {
            setTimeout(async () => {
                console.log("Delay for next request (sun " + sun + "): ", frecuency);
                return await NasaRequest(sun - 1, limit, frecuency);
            }, frecuency);
        } else {
            console.log("Resolve data:", data);    // Code acutally reaches this point
            resolve(data);    // But this doesn't seem to work
        }
    });
};

async function init() {
    try {
        const currentValue = await NasaRequest(2175, false, 2000);
        console.log("currentValue:", currentValue);    // I want to reach this point, but is like the promise never returns
    }catch(err){
        console.error(err);
    }
}

init();

In that moment, I want to return the data in the response to the calling init() function, for what I use resolve(data);. But it doesn't seem to work.

What am I doing wrong?

2
  • .then(data => { return Promise.resolve(data); }) makes no sense, omit it. Commented Jan 25, 2019 at 18:34
  • Never pass an async function as a callback - not to new Promise, not to setTimeout. You should only promisify setTimeout, and then await the timeout. Commented Jan 25, 2019 at 18:35

1 Answer 1

2

The problem is on setTimeout. When you calling setTimeout it returns right away and implicitly return undefined. The subsequence return doesn't matter at that point. If all you want to do, is to pause, and then proceed try something like this

async function requestData(url) {
    var response = await fetch(url);
    if (response.ok) {
        return response.json()
    } else {
        throw new Error(response.status);
    }
}

function sleep(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

async function nasaRequest(sun, limit, freq) {
    var data = await requestData(url + sun + "&api_key=" + apiKey);
    if (data.photos.length === 0 && !limit) {
        await sleep(freq);
        console.log("Delay for next request (sun " + sun + "): ", freq);
        return await nasaRequest(sun - 1, limit, freq);
    } else {
        console.log("Resolve data:", data);
        return data;
    }
};

async function init() {
    try {
        const currentValue = await nasaRequest(2175, false, 2000);
        console.log("currentValue:", currentValue);
    } catch (err) {
        console.error(err);
    }
}

init();

I added a simple sleep function to handle the pause. I also modified requestData (removed then and Promise parts). Note that using this recursive approach you may run into stack overflow. To avoid that problem you can simply use a loop and check against your limit variable.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.