class Task { // _manager = undefined; // _id = 0; // _urls = []; _data = {}; /** * Create a task. * constructor(itemsSelector:string, fieldSelectors:string[]) * constructor(itemsSelector:string, fieldSelectors:string[], url:string, from:number, to:number, interval:number) * constructor(itemsSelector:string, fieldSelectors:string[], url:string, pages:number[]) * constructor(itemsSelector:string, fieldSelectors:string[], urls:string[]) * @param {...any} args */ constructor(...args) { if (!testArgs(...args)) throw new Error(`Invalid call arguments.\n\n${signitures}\n\n`); this._itemsSelector = args.shift(); this._fieldSelectors = args.shift(); this._urls = parseUrls(...args); } get urls() { return this._urls; } get data() { return this._data; } get results() { return this._urls.reduce((p, c) => { return p.concat(this._data[c]); }, []); } clean() { this._data = {}; } async execute(tab, upstreamData) { if (!tab) throw new Error("No tab to execute the task."); if (!this._urls.length) { if (upstreamData) { this._urls = parseUrls(upstreamData); } else { this._urls = [await queryUrl(tab)]; } } return this._urls.reduce((p, url, i) => p.then( results => { if (i > 0) { if (!MSG_URL_SKIPPED.isEqual(results)) { let lastURL = this._urls[i - 1]; this._data[lastURL] = results; } } return this._data[url] ? MSG_URL_SKIPPED : redirectTab(tab, url).then( () => extractTabData(tab, this._itemsSelector, this._fieldSelectors) ); } ), Promise.resolve(null)).then( results => { if (!MSG_URL_SKIPPED.isEqual(results)) { let lastURL = this._urls[this._urls.length - 1]; this._data[lastURL] = results; return; } } ); } }