如何在条件满足时让CronJob跳过tweet()函数执行?
解决方案
问题分析
当前代码存在几个核心问题导致无法实现“条件触发时跳过发推”的需求:
price.js中的条件判断逻辑错误:if (Price < 0.1 || null || undefined)会永远为真,因为null和undefined在逻辑或中会被视为真,无论Price是什么值price.js自身捕获了错误,导致错误无法传递到tweet()函数,使得tweet()会继续执行发推操作- CronJob 中调用
tweet()未使用await,导致日志打印时机错误,且无法正确处理异步错误
步骤1:修复price.js的逻辑和错误处理
修正条件判断,并移除自身的catch块,让错误可以冒泡到上层,同时确保浏览器资源正确释放:
// MODULES const puppeteer = require("puppeteer"); // Url where we get and scrape the data from const url = "https://www.sec.gov/edgar/search/#/dateRange=30d&category=custom&forms=4"; let browser; module.exports = async () => { try { browser = await puppeteer.launch(); const [page] = await browser.pages(); //Set User Agent const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"; await page.setUserAgent(ua); //Go to page from URL and reload await page.goto(url, {waitUntil: "domcontentloaded", timeout: 0}); await page.reload({waitUntil: "domcontentloaded"}); //Get success response and check if url ends with .xml const responseP = page.waitForResponse(res => res.status() === 200 && res.url().endsWith(".xml") ); //Click on Form 4 link to the left const a = await page.waitForSelector(".filetype .preview-file"); await a.click(); const html = await (await responseP).text(); await page.evaluate(html => document.body.outerHTML = html, html); //Get the info about the stocks price const price = await page.$$eval(".FormText", els => { const targetEl = els.find(e => e.textContent.trim() === "$"); if (!targetEl) return null; // 处理找不到目标元素的情况 return targetEl.parentNode.textContent.replace("$", "").replace("(1)", "").trim(); }); const Price = parseInt(price); //Convert price from string to number // 修正条件判断逻辑 if (Price === null || Price === undefined || Price < 0.1) { throw new Error("Price is too low or invalid"); } return Price; } finally { await browser?.close(); // 确保浏览器始终被关闭,避免内存泄漏 } };
步骤2:修改index.js的发推和定时任务逻辑
提前获取并校验数据,不符合条件时直接跳过发推;同时使用await确保异步操作完成:
// MODULES const rwClient = require("./TwitterClient.js"); const cronjob = require("cron").CronJob; const priceModule = require("./price"); const nameModule = require("./name"); const dateModule = require("./date"); const stockModule = require("./stock"); const numShares = require("./numShares.js"); (async () => { // Async function that creates the Tweet const tweet = async () => { try { // 提前获取所有数据,方便校验 const price = await priceModule(); const name = await nameModule(); const shares = await numShares(); const stock = await stockModule(); const date = await dateModule(); // 双重校验(可选,确保万无一失) if (price < 0.1) { console.log("Skipping tweet: Price is too low"); return; } // 计算总金额 const totalAmount = shares * price; // 执行发推 await rwClient.v2.tweet( `New insider trade! (form 4 filed)\n\n` + `${name} bought ${shares} shares at $${price}\n\n` + `Total Amount Purchased: $${totalAmount}\n` + `Stock: ${stock}\n` + `Date: ${date}\n` ); console.log("Tweet sent successfully"); } catch (error) { console.error("Skipping tweet due to error:", error.message); } } // CronJob, starts from 10 am to 8pm EST const job = new cronjob("0 14-23 * * *", async () => { await tweet(); // 等待发推逻辑执行完成 }); job.start(); console.log("CronJob started"); })();
关键修改说明
- price.js:修复了条件判断的逻辑错误,移除自身
catch让错误向上传递,通过finally确保浏览器资源释放 - index.js:
- 提前获取所有数据并校验,不符合条件时直接返回跳过发推
- 使用模板字符串替代繁琐的字符串拼接
- CronJob 回调改为
async函数,用await保证异步操作完成后再结束本次任务 - 细化日志输出,便于排查问题
修改后,当价格不符合条件时,本次tweet()会直接跳过执行,应用会持续运行,不会崩溃或停止定时任务。
内容的提问来源于stack exchange,提问作者Jojo Amankwa
相关产品推荐
相关产品推荐

