Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sahwar/64fac34b9c787083f01181352ab921fc to your computer and use it in GitHub Desktop.
Save sahwar/64fac34b9c787083f01181352ab921fc to your computer and use it in GitHub Desktop.
async await in chrome extension
/**
* 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