Files
data-extracter-extesion/scripts/background/messaging.js

77 lines
2.8 KiB
JavaScript

/**
* Sending a message to target tab repeatedly until the response is not undefined.
* @param {object} tab the table where to send the message
* @param {object} req the request data.
* @param {function} dataChecker (reulst:any, err:error, tryCount:number) => any.
* Check and decide what value finally returns.
* Return undefined to make 'sendMessage' retry.
* Return MSG_USER_ABORT to cancel this promise.
* @param {number} interval retry interval, default: 500ms.
* @param {number} limit retry limit, default: 0, no limit.
* @param {string} log messages logged to console.
* @return {Promise} a promise of the response.
*/
function sendMessage(tab, req, log, dataChecker, interval, limit = 0) {
interval = interval || 500;
limit = limit && !isNaN(limit) ? limit : 0;
let count = 0;
return new Promise((resolve, reject) => {
loop();
async function loop() {
logger.debug("Request for", req.action);
let tabAvailable = await getTabByID(tab.id);
if (!tabAvailable) {
reject("Task interrupted due to the target tab is closed.");
return;
}
if (limit && count >= limit) {
reject(`sendMessage loop limit ${limit} reached.`);
return;
}
count++;
chrome.tabs.sendMessage(tab.id, req, async r => {
// check error but do nothing.
// do not interrupt promise chains even if error, or the task always fail when:
// a tab is newly created, and the content scripts won't have time to initialize
let err = chrome.runtime.lastError;
let result = r;
if (dataChecker) {
result = await dataChecker(r, err, count);
if (MSG_USER_ABORT.isEqual(result)) {
reject(MSG_USER_ABORT.message);
}
}
let flag = result !== undefined && result !== null;
if (log) logger.info(log, flag ? '(OK)' : '(failed)');
if (flag) {
resolve(result);
} else {
setTimeout(() => {
loop();
}, interval);
}
});
}
});
}
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (!request.action || !request.action.startsWith(EXT_NAME)) {
return;
}
switch (request.action) {
case ACTION_UPLOAD_STATE:
sendResponse('recieved!');
__EXTRACTOR_STATE__ = request.state;
logger.info(`State (${request.name}) recieved. To load it: some_var = new Extractor().load()`);
break;
default:
sendResponse("Request not supported.");
break;
}
});