Promise 可以递归吗

我有一个异步获取数据的方法:

getData: () => {
    return new Promise((resolve, reject) => {
        axios.get('/api/getData').then(res => {
            /* 存在下面两种可能返回 */
            /* 接口正确返回 */
            {
                status: 1,
                msg: '获取成功',
                data: {...}
            }
            /* 接口错误返回 */
            {
                status: 429,
                msg: '接口调用最大频次为1req/s'
            }
        })
    })
}

因为错误的返回是因为接口调用频次过高,所以就想如果返回429就等1秒后再重发请求:

getData: () => {
    return new Promise((resolve, reject) => {
        axios.get('/api/getData').then(res => {
            if (res.status === 1) {
                resolve(res.data)
            } else {
                reject()
            }
        })
    }).catch(() => {
        // 这里该如何写?
        // setTimeout(() => {
        //     getData().then()?
        // }, 1000)        
    })
}

请教一下如何在promise里写递归(也不完全叫递归,就是轮询,正确返回就跳出)啊?

阅读 6.6k
3 个回答

大概是这么个逻辑,没调试,可能有错。异步递归比较难写,用 await 好写些。

async function getData() {
    // 不知道 429 是怎么返回的,就当是 res.data.code 吧

    async function tryFetch(times = 0) {
        // 如果有错,直接抛出去了,不会重试
        const { data } = await fetch();

        // times < 3 这个条件,表示只重试 3 次
        if (data.code === 429 && times < 3) {
            await new Promise(async (resolve) => {
                setTimeout(() => {
                    resolve(await tryFetch(times + 1));
                }, 1000);
            })
        }

        return data;
    }

    function fetch() {
        return new Promise((resolve, reject) => {
            axios.get('/api/getData').then(res => {
                if (res.status === 1) {
                    resolve(res.data)
                } else {
                    reject()
                }
            })
        })
    }
}

如果不用递归,用循环,逻辑会更清楚一些(也没调试,可能有错)

async function getData() {
    // 不知道 429 是怎么返回的,就当是 res.data.code 吧
    // i < 3 表示最多试 3 次
    for (let i = 0; i < 3; i++) {
        const { data } = await fetch();
        if (data.code === 429) {
            await delay(1000);
            continue;
        }

        return data;
    }

    function delay(milliSeconds) {
        return new Promise(resolve => setTimeout(resolve, milliSeconds));
    }

    function fetch() {
        return new Promise((resolve, reject) => {
            axios.get('/api/getData').then(res => {
                if (res.status === 1) {
                    resolve(res.data)
                } else {
                    reject()
                }
            })
        })
    }
}
getData: () => {
    return axios.get('/api/getData').then(res => {
        if(res.status === 1) {
            return res.data
        }else {
            return Promise.reject()
        }
    })
}

this.getData().then(data => {
    console.log(data)
}).catch(() => {
    setTimeout(() => {
        this.getData()
    }, 1000)
})
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏