Optimize: reuse tab and smart polling for faster checks
- Keep tab open between checks (no create/close overhead) - Poll for products every 500ms instead of fixed 10s wait - Exit early as soon as products are found - Max wait reduced to 8 seconds - Should reduce check time from ~15-20s to ~3-8s Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ const DEFAULT_CONFIG = {
|
|||||||
// Store known products
|
// Store known products
|
||||||
let knownProducts = {};
|
let knownProducts = {};
|
||||||
let config = DEFAULT_CONFIG;
|
let config = DEFAULT_CONFIG;
|
||||||
|
let persistentTabId = null; // Keep tab open for faster refreshes
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
chrome.runtime.onInstalled.addListener(() => {
|
chrome.runtime.onInstalled.addListener(() => {
|
||||||
@@ -129,53 +130,82 @@ async function runStockCheck() {
|
|||||||
async function fetchAndParseProducts(url) {
|
async function fetchAndParseProducts(url) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
// Create a tab to load the page
|
let tabId;
|
||||||
const tab = await chrome.tabs.create({ url, active: false });
|
let isNewTab = false;
|
||||||
|
|
||||||
console.log(`Created tab ${tab.id} for ${url}`);
|
// Reuse existing tab or create new one
|
||||||
|
if (persistentTabId) {
|
||||||
|
try {
|
||||||
|
const tab = await chrome.tabs.get(persistentTabId);
|
||||||
|
tabId = tab.id;
|
||||||
|
console.log(`Reusing tab ${tabId}, refreshing...`);
|
||||||
|
await chrome.tabs.update(tabId, { url });
|
||||||
|
} catch (e) {
|
||||||
|
// Tab was closed, create new one
|
||||||
|
persistentTabId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!persistentTabId) {
|
||||||
|
const tab = await chrome.tabs.create({ url, active: false });
|
||||||
|
tabId = tab.id;
|
||||||
|
persistentTabId = tabId;
|
||||||
|
isNewTab = true;
|
||||||
|
console.log(`Created new tab ${tabId}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for tab to finish loading
|
// Wait for tab to finish loading
|
||||||
const waitForLoad = () => {
|
const waitForLoad = () => {
|
||||||
return new Promise((res) => {
|
return new Promise((res) => {
|
||||||
const listener = (tabId, changeInfo) => {
|
const listener = (tid, changeInfo) => {
|
||||||
if (tabId === tab.id && changeInfo.status === "complete") {
|
if (tid === tabId && changeInfo.status === "complete") {
|
||||||
chrome.tabs.onUpdated.removeListener(listener);
|
chrome.tabs.onUpdated.removeListener(listener);
|
||||||
res();
|
res();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
chrome.tabs.onUpdated.addListener(listener);
|
chrome.tabs.onUpdated.addListener(listener);
|
||||||
|
|
||||||
// Timeout after 30 seconds
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
chrome.tabs.onUpdated.removeListener(listener);
|
chrome.tabs.onUpdated.removeListener(listener);
|
||||||
res();
|
res();
|
||||||
}, 30000);
|
}, 20000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
await waitForLoad();
|
await waitForLoad();
|
||||||
console.log(`Tab ${tab.id} loaded`);
|
console.log(`Tab ${tabId} loaded`);
|
||||||
|
|
||||||
// Give extra time for dynamic content to load
|
// Smart wait: poll for products instead of fixed wait
|
||||||
console.log("Waiting for dynamic content...");
|
|
||||||
await new Promise(r => setTimeout(r, 10000)); // 10 seconds for slow loads
|
|
||||||
|
|
||||||
// Send message to content script to extract products
|
|
||||||
let products = [];
|
let products = [];
|
||||||
|
const startTime = Date.now();
|
||||||
|
const maxWait = 8000; // Max 8 seconds
|
||||||
|
const pollInterval = 500; // Check every 500ms
|
||||||
|
|
||||||
|
while (Date.now() - startTime < maxWait) {
|
||||||
|
try {
|
||||||
|
// Inject content script if needed
|
||||||
try {
|
try {
|
||||||
const response = await chrome.tabs.sendMessage(tab.id, { type: "extractProducts" });
|
|
||||||
products = response || [];
|
|
||||||
console.log(`Content script returned ${products.length} products`);
|
|
||||||
} catch (e) {
|
|
||||||
console.log("Content script not ready, injecting manually...");
|
|
||||||
// Inject content script if not already there
|
|
||||||
await chrome.scripting.executeScript({
|
await chrome.scripting.executeScript({
|
||||||
target: { tabId: tab.id },
|
target: { tabId },
|
||||||
files: ["content.js"]
|
files: ["content.js"]
|
||||||
});
|
});
|
||||||
await new Promise(r => setTimeout(r, 500));
|
} catch (e) { /* Already injected */ }
|
||||||
const response = await chrome.tabs.sendMessage(tab.id, { type: "extractProducts" });
|
|
||||||
|
await new Promise(r => setTimeout(r, pollInterval));
|
||||||
|
|
||||||
|
const response = await chrome.tabs.sendMessage(tabId, { type: "extractProducts" });
|
||||||
products = response || [];
|
products = response || [];
|
||||||
|
|
||||||
|
if (products.length > 0) {
|
||||||
|
console.log(`Found ${products.length} products after ${Date.now() - startTime}ms`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Content script not ready yet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (products.length === 0) {
|
||||||
|
console.log(`No products found after ${maxWait}ms`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply keyword filter
|
// Apply keyword filter
|
||||||
@@ -187,13 +217,11 @@ async function fetchAndParseProducts(url) {
|
|||||||
console.log(`After keyword filter: ${products.length} products`);
|
console.log(`After keyword filter: ${products.length} products`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the tab
|
// Don't close tab - keep for reuse
|
||||||
await chrome.tabs.remove(tab.id);
|
|
||||||
console.log(`Closed tab ${tab.id}`);
|
|
||||||
|
|
||||||
resolve(products);
|
resolve(products);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
persistentTabId = null; // Reset on error
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user