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()回调中,代码可运行但会超时无法完成。
核心问题分析
- 异步任务未等待就返回响应:原代码中
res.status(200).json({ success: true });是同步执行的,Vercel Serverless函数在返回响应后会立即终止进程,导致Promise.all内的runTest等异步逻辑根本没机会执行。 - 超时限制触发: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
相关产品推荐
相关产品推荐

