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:
2020-01-15 18:28:28 +08:00
parent 7644a1363f
commit d82010686d
3 changed files with 65 additions and 22 deletions

View File

@ -1,5 +1,6 @@
import { Actions, Request } from "../common";
import { sendMessage } from "./messaging";
import { logger } from "./common";
/**
* 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
* @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 = {
action: Actions.EXTRACT,
itemsSelector: itemsSelector,
@ -49,7 +50,13 @@ export function extractTabData(tab, itemsSelector, fieldSelectors) {
}
let checker = (result, err, tryCount) => {
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 [];
} else {
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() {
return new Promise((resolve, reject) => {
chrome.windows.create(

View File

@ -31,7 +31,7 @@ export function sendMessage<T>(
loop();
async function loop() {
logger.debug("Request for", req.action);
logger.debug("Request for", Actions[req.action]);
let tabAvailable = await getTabByID(tab.id);
if (!tabAvailable) {
reject("Task interrupted due to the target tab is closed.");

View File

@ -1,5 +1,5 @@
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 { ExtractResult } from "./result";
import { messageSubscribers, ActionSubscriber } from "./messaging";
@ -14,6 +14,7 @@ export class Task {
private _fieldSelectors: string[];
private _urls: string[] = [];
private _running = false;
private _listeners: ActionSubscriber[] = [];
constructor(options: any, ...arg: any);
constructor(options: any, itemsSelector: string, fieldSelectors: string[]);
@ -56,15 +57,46 @@ export class Task {
}
stop() {
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) {
logger.info("The task is running. Please wait...");
return;
}
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> {
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> {
let pm: Promise<any>;
if (this._options["scrollToBottom"]) {