Last active
March 19, 2024 20:59
-
-
Save BigSully/4468a58848df07736757a73d722d81f5 to your computer and use it in GitHub Desktop.
async await in chrome extension
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Usage: | |
* let cookies = await asyncfy(chrome.cookies.getAll)({ url }) | |
* let tabs = await asyncfy(chrome.tabs.query)({active: true, currentWindow: true}) | |
* | |
* @param fn A function that takes one or more parameters, and the last parameter is a callback which has one or more parameter. The simplest one is chrome.management.getSelf | |
* @returns {function(...[*]): Promise<any>} Return one value if the results array has only one element, else return the whole results array | |
*/ | |
let asyncfy = fn => (...args) => { | |
return new Promise((resolve, reject) => { | |
fn(...args, (...results) => { | |
let { lastError } = chrome.runtime | |
if (typeof lastError !== 'undefined') reject(lastError); | |
else results.length == 1 ? resolve(results[0]) : resolve(results); | |
}); | |
}); | |
} | |
let isObject = function(obj) { | |
var type = typeof obj; | |
return type === 'function' || type === 'object' && !!obj; | |
}; | |
// provide async method to all methods which have one callback. | |
let handler = { | |
get: function(target, prop, receiver) { | |
let value = target[prop] | |
let type = typeof value | |
if(type !== 'undefined') { // including null, false | |
if( type === 'function') return value.bind(target); // correct the this for the functions, since we've substituted the original object to the proxy object | |
return value; | |
} | |
if(prop.endsWith('Async')){ | |
let key = prop.replace(/Async$/, '') | |
let method=target[key] | |
let asyncMethod = asyncfy(method.bind(target)); | |
return asyncMethod; | |
} | |
} | |
} | |
// proxy every leaf object | |
let asyncfyObj = handler => obj => Object.getOwnPropertyNames(obj) | |
.filter(prop => isObject(obj[prop])) | |
.forEach(prop => obj[prop] = new Proxy(obj[prop], handler)) | |
// intercept the getters of all object in chrome member | |
asyncfyObj(handler)(chrome) | |
asyncfyObj(handler)(chrome.storage) | |
// console.log(`active tab: ${JSON.stringify(await getActiveTabAsync())}`) | |
let getActiveTabAsync = async () => { | |
let tabs = await chrome.tabs.queryAsync({active: true, currentWindow: true}); | |
return (tabs && tabs.length > 0) ? tabs[0] : null; | |
} | |
// chrome.storage.local.set({ foo: 'bar' }); | |
// console.log(`foo: ${await getLocalStorageAsync('foo')}`) | |
let getLocalStorageAsync = async key => ( await chrome.storage.local.getAsync([key]) ) [key]; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
// testing put the following snippet in your background script and make sure related permissions have been added to the manifest.json.
(async () => {
console.log(
cookies: ${JSON.stringify(await asyncfy(chrome.cookies.getAll)({ url: 'https://www.stackoverflow.com/' }))}
)console.log(
active tab: ${JSON.stringify(await getActiveTabAsync())}
)chrome.storage.local.set({ 'foo': 'bar'});
console.log(
storage: ${await getLocalStorageAsync('foo')}
)console.log(
extension install type: ${( await chrome.management.getSelfAsync() )['installType']}
)} )()