Extractor.watch() improvements
- only watch current window - stop watch on window close - don't ask user to confirm when fails
This commit is contained in:
		| @ -1,5 +1,6 @@ | |||||||
| import { Actions, Request } from "../common"; | import { Actions, Request } from "../common"; | ||||||
| import { sendMessage } from "./messaging"; | import { sendMessage } from "./messaging"; | ||||||
|  | import { logger } from "./common"; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * redirect tab to url. |  * redirect tab to url. | ||||||
| @ -41,7 +42,7 @@ export function redirectTab(tab: chrome.tabs.Tab, url: string) { | |||||||
|  * @param {Array<string>} fieldSelectors fields selectors for selecting fields (data columns) under each item |  * @param {Array<string>} fieldSelectors fields selectors for selecting fields (data columns) under each item | ||||||
|  * @returns {Promise<string[]>} a promise of extracted data |  * @returns {Promise<string[]>} a promise of extracted data | ||||||
|  */ |  */ | ||||||
| export function extractTabData(tab, itemsSelector, fieldSelectors) { | export function extractTabData(tab: chrome.tabs.Tab, itemsSelector: string, fieldSelectors: string[], askOnfail?: boolean) { | ||||||
|     let req = { |     let req = { | ||||||
|         action: Actions.EXTRACT, |         action: Actions.EXTRACT, | ||||||
|         itemsSelector: itemsSelector, |         itemsSelector: itemsSelector, | ||||||
| @ -49,7 +50,13 @@ export function extractTabData(tab, itemsSelector, fieldSelectors) { | |||||||
|     } |     } | ||||||
|     let checker = (result, err, tryCount) => { |     let checker = (result, err, tryCount) => { | ||||||
|         if (!result || !result.length) { |         if (!result || !result.length) { | ||||||
|             if (tryCount % 20 == 0 && confirm('No data found in current page. \n\nContinue to next page?')) { |             if ( | ||||||
|  |                 tryCount % 20 == 0 && ( | ||||||
|  |                     !askOnfail || | ||||||
|  |                     confirm('No data found in current page. \n\nContinue to next page?') | ||||||
|  |                 ) | ||||||
|  |             ) { | ||||||
|  |                 logger.warn(`Failed after ${tryCount} tries: ${tab.url}`) | ||||||
|                 return []; |                 return []; | ||||||
|             } else { |             } else { | ||||||
|                 return undefined; |                 return undefined; | ||||||
| @ -135,6 +142,25 @@ export async function findIncognitoWindow(): Promise<chrome.windows.Window> { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | export async function getCurrentWindow(): Promise<chrome.windows.Window> { | ||||||
|  |     return new Promise((resolve, reject) => { | ||||||
|  |         chrome.windows.getCurrent( | ||||||
|  |             (windows: chrome.windows.Window) => { | ||||||
|  |                 return resolve(windows); | ||||||
|  |             } | ||||||
|  |         ); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export async function getWindowByID(id: number) { | ||||||
|  |     return new Promise<chrome.windows.Window>((resolve, reject) => { | ||||||
|  |         chrome.windows.get(id, function (window) { | ||||||
|  |             chrome.runtime.lastError; | ||||||
|  |             resolve(window); | ||||||
|  |         }) | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  |  | ||||||
| export async function CreateIncognitoWindow() { | export async function CreateIncognitoWindow() { | ||||||
|     return new Promise((resolve, reject) => { |     return new Promise((resolve, reject) => { | ||||||
|         chrome.windows.create( |         chrome.windows.create( | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ export function sendMessage<T>( | |||||||
|         loop(); |         loop(); | ||||||
|  |  | ||||||
|         async function loop() { |         async function loop() { | ||||||
|             logger.debug("Request for", req.action); |             logger.debug("Request for", Actions[req.action]); | ||||||
|             let tabAvailable = await getTabByID(tab.id); |             let tabAvailable = await getTabByID(tab.id); | ||||||
|             if (!tabAvailable) { |             if (!tabAvailable) { | ||||||
|                 reject("Task interrupted due to the target tab is closed."); |                 reject("Task interrupted due to the target tab is closed."); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { parseUrls } from "./tools"; | import { parseUrls } from "./tools"; | ||||||
| import { queryUrl, redirectTab, scrollToBottom, extractTabData } from "./actions"; | import { queryUrl, redirectTab, scrollToBottom, extractTabData, findIncognitoWindow, getCurrentWindow, getWindowByID } from "./actions"; | ||||||
| import { testArgs, signitures } from "./signiture"; | import { testArgs, signitures } from "./signiture"; | ||||||
| import { ExtractResult } from "./result"; | import { ExtractResult } from "./result"; | ||||||
| import { messageSubscribers, ActionSubscriber } from "./messaging"; | import { messageSubscribers, ActionSubscriber } from "./messaging"; | ||||||
| @ -14,6 +14,7 @@ export class Task { | |||||||
|     private _fieldSelectors: string[]; |     private _fieldSelectors: string[]; | ||||||
|     private _urls: string[] = []; |     private _urls: string[] = []; | ||||||
|     private _running = false; |     private _running = false; | ||||||
|  |     private _listeners: ActionSubscriber[] = []; | ||||||
|  |  | ||||||
|     constructor(options: any, ...arg: any); |     constructor(options: any, ...arg: any); | ||||||
|     constructor(options: any, itemsSelector: string, fieldSelectors: string[]); |     constructor(options: any, itemsSelector: string, fieldSelectors: string[]); | ||||||
| @ -56,15 +57,46 @@ export class Task { | |||||||
|     } |     } | ||||||
|     stop() { |     stop() { | ||||||
|         this._running = false; |         this._running = false; | ||||||
|         messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, this.listener); |         let listener: ActionSubscriber; | ||||||
|  |         while (listener = this._listeners.pop()) { | ||||||
|  |             messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, listener); | ||||||
|         } |         } | ||||||
|     watch() { |     } | ||||||
|  |     async watch() { | ||||||
|         if (this._running) { |         if (this._running) { | ||||||
|             logger.info("The task is running. Please wait..."); |             logger.info("The task is running. Please wait..."); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         this._running = true; |         this._running = true; | ||||||
|         messageSubscribers.addListener(Actions.REPORT_NEW_PAGE, this.listener); |         let window = await findIncognitoWindow() || await getCurrentWindow(); | ||||||
|  |         if (!window) { | ||||||
|  |             logger.info("No window to watch..."); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         let listener: ActionSubscriber = async (request, sender, sendResponse) => { | ||||||
|  |             let findWindow = await getWindowByID(window.id); | ||||||
|  |             if (!findWindow) { | ||||||
|  |                 // stop watch on window close. | ||||||
|  |                 messageSubscribers.removeListener(Actions.REPORT_NEW_PAGE, listener); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             // only watch current window. | ||||||
|  |             if (sender.tab.windowId != window.id) return; | ||||||
|  |             let pm = this.makeOptionalTasks(sender.tab); | ||||||
|  |             return pm.then( | ||||||
|  |                 () => extractTabData(sender.tab, this._itemsSelector, this._fieldSelectors, false) | ||||||
|  |             ).then( | ||||||
|  |                 results => { | ||||||
|  |                     if (results && results.length) { | ||||||
|  |                         this.saveResult(results, sender.tab.url); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             ).catch( | ||||||
|  |                 e => logger.error(e) | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |         this._listeners.push(listener); | ||||||
|  |         messageSubscribers.addListener(Actions.REPORT_NEW_PAGE, listener); | ||||||
|     } |     } | ||||||
|     async execute(tab: chrome.tabs.Tab, upstreamData?: ExtractResult): Promise<void> { |     async execute(tab: chrome.tabs.Tab, upstreamData?: ExtractResult): Promise<void> { | ||||||
|         if (!tab) return Promise.reject("No tab to execute the task."); |         if (!tab) return Promise.reject("No tab to execute the task."); | ||||||
| @ -108,21 +140,6 @@ export class Task { | |||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|     private listener: ActionSubscriber = (request, sender, sendResponse) => { |  | ||||||
|         sendResponse('recieved!'); |  | ||||||
|         let pm = this.makeOptionalTasks(sender.tab); |  | ||||||
|         return pm.then( |  | ||||||
|             () => extractTabData(sender.tab, this._itemsSelector, this._fieldSelectors) |  | ||||||
|         ).then( |  | ||||||
|             results => { |  | ||||||
|                 if (results && results.length) { |  | ||||||
|                     this.saveResult(results, sender.tab.url); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         ).catch( |  | ||||||
|             e => logger.error(e) |  | ||||||
|         ) |  | ||||||
|     } |  | ||||||
|     private makeOptionalTasks(tab: chrome.tabs.Tab): Promise<any> { |     private makeOptionalTasks(tab: chrome.tabs.Tab): Promise<any> { | ||||||
|         let pm: Promise<any>; |         let pm: Promise<any>; | ||||||
|         if (this._options["scrollToBottom"]) { |         if (this._options["scrollToBottom"]) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user