递归异步/等待请求不会返回到调用函数

时间:2019-01-25 17:36:30

标签: javascript recursion async-await

每当收到的响应具有async/await时,我就会向length === 0进行递归请求。问题是,当某些请求返回所需的数据时,promise的resolve(data);部分似乎不起作用。

因此,在我的代码中,我已经到达进行多次递归调用的地步,最后收到的响应长度不为0。

注意:如果要测试代码,Github中发布了许多API密钥。

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();

那一刻,我想返回init()调用函数的响应中的数据。但这似乎不起作用。

我在做什么错了?

1 个答案:

答案 0 :(得分:2)

问题出在setTimeout上。调用setTimeout时,它将立即返回,并隐式返回undefined。子序列返回在这一点上无关紧要。如果您只想暂停一下,然后继续尝试类似的事情

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();

我添加了一个简单的sleep函数来处理暂停。我还修改了requestData(删除了thenPromise部分)。 请注意,使用这种递归方法可能会遇到堆栈溢出。为避免该问题,您可以简单地使用循环并检查您的limit变量。