migrate to typescript, with fixes
This commit is contained in:
94
src/background/messaging.ts
Normal file
94
src/background/messaging.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { EXT_NAME, ACTION_UPLOAD_STATE } from "../common";
|
||||
import { getTabByID } from "./actions";
|
||||
import { caches, logger } from "./common";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export function sendMessage<T>(
|
||||
tab: chrome.tabs.Tab,
|
||||
req,
|
||||
log?: string,
|
||||
dataChecker?: (r: T, err: chrome.runtime.LastError, count: number) => T | Promise<T>,
|
||||
interval?: number,
|
||||
limit?: number
|
||||
) {
|
||||
interval = interval || 500;
|
||||
limit = isNaN(limit) ? 0 : limit;
|
||||
let count = 0;
|
||||
return new Promise<T>((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: T) => {
|
||||
// check error but do nothing until dataChecker.
|
||||
let err = chrome.runtime.lastError;
|
||||
let result: T = r;
|
||||
|
||||
if (dataChecker) {
|
||||
let pms = dataChecker(r, err, count);
|
||||
// don't catch if it's not a Promise
|
||||
if (pms instanceof Promise) {
|
||||
let checkerError: any;
|
||||
pms = pms.catch(e => checkerError = e);
|
||||
result = await pms;
|
||||
if (checkerError) {
|
||||
reject(checkerError);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
result = pms;
|
||||
}
|
||||
}
|
||||
|
||||
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!');
|
||||
caches.setState(request.name, request.state)
|
||||
break;
|
||||
default:
|
||||
sendResponse("Request not supported.");
|
||||
break;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user