migrate to typescript, with fixes

This commit is contained in:
2020-01-14 16:37:50 +08:00
parent 3d375261df
commit f06a6f4e78
32 changed files with 5071 additions and 394 deletions

View 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;
}
});