diff --git a/readme.md b/readme.md index 584bed6..6d72bba 100644 --- a/readme.md +++ b/readme.md @@ -13,10 +13,14 @@ All you need to do is: ## Qucik Start Extract current page + ```js $('.item', ['a', 'a@href']); +new Extractor().task('.item', ['a', 'a@href']).start(); ``` +> `$(...args)` is the short form of `new Extractor().task(...args).start();`, which is introduced later. + Extract multiple pages (1-10, interval 1) ```js @@ -54,6 +58,15 @@ function (itemsSelector:string, fieldSelectors:string[], urls:ExtractResult) Close the target tab, in which current tasks is running. +Or use `job.stop()`: + +```js +job = new Extractor().task('.search-list-item', ['a@href'], ["http://sample.com/abc"]) + .task('list-item', ["a.title", "p.content"]) + .start(); +job.stop(); +``` + ## Extract Attributes. e.g.: link text and target (use 'selector@attribute') diff --git a/src/background/extractor.ts b/src/background/extractor.ts index f8acb7c..cd72c96 100644 --- a/src/background/extractor.ts +++ b/src/background/extractor.ts @@ -51,14 +51,19 @@ export class Extractor { /** * Start the task chain. */ - async start() { + start() { return this._startTasks(0); } + stop() { + for (let i = 0; i < this._tasks.length; i++) { + this._tasks[i].stop(); + } + } /** * restart from specified task, but don't restart the previous tasks. * @param {number} from where to restart the tasks, begins with 0 */ - async restart(from: number = 0) { + restart(from: number = 0) { let id = this._checkTaskId(from, 0); if (id < 0) return; for (let i = id; i < this._tasks.length; i++) { diff --git a/src/background/task.ts b/src/background/task.ts index a45b6ad..b99f91d 100644 --- a/src/background/task.ts +++ b/src/background/task.ts @@ -10,6 +10,7 @@ export class Task { private _itemsSelector: string; private _fieldSelectors: string[]; private _urls: string[] = []; + private _running = false; constructor(options: any, ...arg: any); constructor(options: any, itemsSelector: string, fieldSelectors: string[]); @@ -49,8 +50,13 @@ export class Task { this._data_keys = []; return this; } + stop() { + this._running = false; + } async execute(tab: chrome.tabs.Tab, upstreamData?: ExtractResult): Promise { if (!tab) return Promise.reject("No tab to execute the task."); + if (this._running) return Promise.reject("The task is running. Please wait..."); + this._running = true; let urls = this._urls if (!urls.length) { if (upstreamData) { @@ -63,6 +69,10 @@ export class Task { this._data[key] = results; this._data_keys.push(key); } + let runningCheck = (fn: () => Promise): Promise => { + if (!this._running) return Promise.reject("The task is stopped by user."); + return fn(); + } return urls.reduce((p, url, i) => p.then( results => { if (i > 0 && results instanceof Array) { @@ -70,12 +80,13 @@ export class Task { saveResult(results, lastURL); } if (this._data[url]) return; - let pms: Promise = redirectTab(tab, url); + + let pms: Promise = runningCheck(() => redirectTab(tab, url)); if (this._options["scrollToBottom"]) { - pms = pms.then(() => scrollToBottom(tab)); + pms = pms.then(() => runningCheck(() => scrollToBottom(tab))); } return pms.then( - () => extractTabData(tab, this._itemsSelector, this._fieldSelectors) + () => runningCheck(() => extractTabData(tab, this._itemsSelector, this._fieldSelectors)) ); } ), Promise.resolve(null)).then( @@ -83,9 +94,14 @@ export class Task { if (results && results.length) { let lastURL = urls[urls.length - 1]; saveResult(results, lastURL); - return; + this._running = false; } } + ).catch( + e => { + this._running = false; + return Promise.reject(e); + } ); } } \ No newline at end of file