You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Lambda环境下异步函数15秒重试超时失效问题求助

问题:Vercel(AWS Lambda)环境下异步重试的超时控制失效

本地运行正常的15秒超时重试逻辑,部署到Vercel(基于AWS Lambda)后,setTimeout被完全忽略,fetchData函数会持续运行直到获取正确响应或触发服务器默认60秒超时。

原代码如下:

router.get('/test', async (req, res) => {
    try {
        const browser = await playwright.launchChromium({ 
        headless: false });
        const context = await browser.newContext();
        const page = await context.newPage();

        let timeout = false;

        let fetchDataTimeout = setTimeout(() => {
        timeout = true;
        }, 15000);

        const fetchData = async () => {
            await page.type('#code', '6824498040');
            let data = await (
                await Promise.all([
                    page.waitForResponse(
                        (response) =>
                            response.url() === `${env.API_URL2}` && response.status() === 200,
                        { timeout: 10000 },
                    ),
                    page.click('#btn-check'),
                ])
            )[0].json();
            if (data.errors && !timeout) {
                await page.reload();
                return await fetchData();
            } else {
                clearTimeout(fetchDataTimeout);
                return data;
            }
        };
        let data = await fetchData();
        await browser.close();

        res.json({
            status: 200,
            message: data,
        });
    } catch (error) {
        console.error(error);
        return res.status(500).send({ 'Server Error': `${error}` });
    }
});

解决方案:用Promise.race实现可取消的超时控制

AWS Lambda的执行环境对同步/异步逻辑的处理和本地Node.js存在差异,直接用setTimeout标记全局变量的方式不可靠。正确的做法是把超时逻辑包装成带取消功能的Promise,通过Promise.race让重试逻辑和超时逻辑竞争,同时支持在成功获取数据后终止超时流程。

修改后的代码如下:

router.get('/test', async (req, res) => {
    try {
        const browser = await playwright.launchChromium({ 
            headless: false 
        });
        const context = await browser.newContext();
        const page = await context.newPage();

        // 封装带取消功能的超时Promise
        const createTimeoutPromise = () => {
            let timeoutId;
            const promise = new Promise((_, reject) => {
                timeoutId = setTimeout(() => {
                    reject(new Error('请求超时,已停止重试'));
                }, 15000);
            });
            return {
                promise,
                cancel: () => clearTimeout(timeoutId)
            };
        };

        const { promise: timeoutPromise, cancel: cancelTimeout } = createTimeoutPromise();

        // 重试逻辑封装
        const fetchDataWithRetry = async () => {
            await page.type('#code', '6824498040');
            const response = await Promise.all([
                page.waitForResponse(
                    (res) => res.url() === `${env.API_URL2}` && res.status() === 200,
                    { timeout: 10000 }
                ),
                page.click('#btn-check')
            ])[0];
            const data = await response.json();
            
            if (data.errors) {
                await page.reload();
                return fetchDataWithRetry();
            }
            return data;
        };

        // 让重试逻辑与超时逻辑竞争执行
        const data = await Promise.race([
            fetchDataWithRetry(),
            timeoutPromise
        ]);

        // 成功获取数据,立即取消超时定时器
        cancelTimeout();
        await browser.close();

        res.json({
            status: 200,
            message: data
        });
    } catch (error) {
        console.error(error);
        // 确保浏览器关闭,避免资源泄漏
        if (typeof browser !== 'undefined') {
            await browser.close();
        }
        return res.status(500).send({ 'Server Error': error.message });
    }
});

关键改动说明:

  • 带取消的超时Promise:通过封装返回Promise和取消方法,成功获取数据后调用cancelTimeout清除定时器,避免不必要的超时触发。
  • Promise.race竞争机制:让重试逻辑和超时逻辑同时执行,哪个先完成就取哪个结果——超时先到则抛出错误终止流程,成功获取数据则返回结果并取消超时。
  • 移除全局timeout变量:不再依赖外部变量控制重试,完全通过Promise状态和递归逻辑实现,避免Lambda环境下的变量状态异常。

内容的提问来源于stack exchange,提问作者lenny73

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 22:05:29