allow user decision when some action fails

This commit is contained in:
2020-01-13 16:47:52 +08:00
parent 21d3dfb247
commit 13e233fbe7
5 changed files with 70 additions and 80 deletions

View File

@ -1,18 +1,21 @@
/**
* Repeatedly sending a message to target tab until the response is detected good.
* 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} cond success condition function, r:any=>boolean
* @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, cond, interval, limit = 0) {
function sendMessage(tab, req, log, dataChecker, interval, limit = 0) {
interval = interval || 500;
limit = limit && !isNaN(limit) ? limit : 0;
count = 0;
let count = 0;
return new Promise((resolve, reject) => {
loop();
@ -30,16 +33,22 @@ function sendMessage(tab, req, log, cond, interval, limit = 0) {
return;
}
count++;
chrome.tabs.sendMessage(tab.id, req, r => {
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
chrome.runtime.lastError;
let flag = !cond || cond(r);
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(r);
resolve(result);
} else {
setTimeout(() => {
loop();