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

Cron Job本地正常但Vercel上runTest函数不执行问题排查

Vercel部署后API Cron任务异常问题排查

问题描述

本地用vercel dev运行时功能正常,但部署到Vercel后访问https://<vercel-url>/api/cron仅返回{"success":true},runTest函数完全未执行。若将res.status(200).json({ success: true });移至Promise.all的then()回调中,代码可运行但会超时无法完成。

核心问题分析

  1. 异步任务未等待就返回响应:原代码中res.status(200).json({ success: true });是同步执行的,Vercel Serverless函数在返回响应后会立即终止进程,导致Promise.all内的runTest等异步逻辑根本没机会执行。
  2. 超时限制触发:Vercel Serverless函数默认超时10秒,最长可配置至60秒,但原代码中WebPageTest的timeout设为240秒,远超平台限制,导致移至then回调后整体流程超时。

修复方案

修改后的代码

const WebPageTest = require("webpagetest");
const { google } = require('googleapis');

// 改为async handler,确保等待所有异步任务完成
export default async function handler(req, res) {
    const wpt = new WebPageTest("www.webpagetest.org", process.env.WEBPAGETEST_API_KEY);

    const urls = [
        "https://somedomain.com",
        "https://anotherdomain.com"
    ];

    // 调整WebPageTest超时至Vercel允许的范围内
    const options = {
        firstViewOnly: true,
        location: "Dulles:Chrome",
        pollResults: 5,
        timeout: 50, // 留10秒余量给其他操作
        lighthouse: 1
    };

    const runTest = (wpt, url, options) => {
        return new Promise((resolve, reject) => {
            console.log(`Submitting test for ${url}...`);
            // 移除async回调,避免Promise错误捕获失效
            wpt.runTest(url, options, (err, result) => {
                result ? resolve(result) : reject(err);
            });
        });
    };

    const auth = new google.auth.GoogleAuth({
        keyFile: "keyfile.json",
        scopes: "https://www.googleapis.com/auth/spreadsheets", 
    });

    try {
        // 复用Auth实例,避免循环内重复创建
        const authClientObject = await auth.getClient();
        const googleSheetsInstance = google.sheets({ version: "v4", auth: authClientObject });
        const spreadsheetId = process.env.GOOGLE_SPREADSHEET_ID;

        // 等待所有任务完成
        await Promise.all(
            urls.map(async (url) => {
                const result = await runTest(wpt, url, options);
                if (result.data) {
                    // 移除不必要的Sheet查询,减少耗时
                    await googleSheetsInstance.spreadsheets.values.append({
                        auth: authClientObject,
                        spreadsheetId,
                        range: "Sheet1!A:A",
                        valueInputOption: "USER_ENTERED",
                        resource: {
                            values: [[`https://www.webpagetest.org/jsonResult.php?test=${result.data.id}&pretty=1`]]
                        },
                    });
                }
            })
        );
        
        res.status(200).json({ success: true });
    } catch (e) {
        console.error(e);
        res.status(500).json({ success: false, error: e.message });
    }
};

关键修改点

  • 将handler改为async函数,用await等待Promise.all完成后再返回响应,避免Vercel提前终止进程。
  • 把WebPageTest的timeout调整到50秒以内,适配Vercel Serverless函数的60秒最长超时限制。
  • 移除不必要的spreadsheets.get和values.get请求,减少额外耗时。
  • 修复runTest中的async回调问题,确保Promise能正确捕获错误。
  • 复用Google Auth实例,避免循环内重复创建资源。

Vercel环境调试方法

  • 查看函数日志:在Vercel控制台的「Functions」页面找到对应API函数,查看实时日志,通过console.log/console.error输出定位具体错误。
  • 调整超时配置:在Vercel控制台的函数设置中,将超时时间调至最大值60秒(默认10秒)。
  • 拆分任务测试:将复杂异步逻辑拆分为单个任务测试(如单独测试WebPageTest调用、Google Sheets写入),逐步排查问题。
  • 改用Edge Functions(可选):若Serverless函数超时问题无法解决,可尝试改用Edge Functions,但需注意Edge Functions不支持文件系统,需将keyfile.json转换为环境变量形式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:07:16