Skip to content

Instantly share code, notes, and snippets.

@phryneas
Created June 11, 2017 12:42
Show Gist options
  • Save phryneas/86695a60aee3b7c290c2f664bdad01bb to your computer and use it in GitHub Desktop.
Save phryneas/86695a60aee3b7c290c2f664bdad01bb to your computer and use it in GitHub Desktop.
transparent asynchronous calls in a firefox plugin
(async function test() {
console.log("starting BgCallExample");
let x = new BgCallExample(true, "x");
console.log(await x.someMethod("test1"));
console.log(await x.someOtherMethod("test2"));
})();
/**
* @property {boolean} synchronousCalls
* @property {string} instanceName
*/
class BgCallExample {
/**
* @param {boolean} synchronousCalls
* @param {string} instanceName
*/
constructor(synchronousCalls = false, instanceName){
this.synchronousCalls = synchronousCalls;
this.instanceName = instanceName;
if (this.synchronousCalls){
this.registerCall(this.someMethod);
this.registerCall(this.someOtherMethod);
}
}
/**
*
* @param {Function<Promise>} callToRegister
*/
registerCall(callToRegister){
let actionName = this.constructor.name + "." + callToRegister.name;
browser.runtime.onMessage.addListener(
/**
*
* @param request
* @param {string} request.action
* @param {Array} request.params
* @param sender
* @param {Function} sendResponse
*/
(request, sender, sendResponse) => {
if (request.action !== actionName) { return; }
(callToRegister.bind(this))(...request.params).then(sendResponse);
return true;
}
);
}
/**
*
* @param {Function} originalMethod
* @param {Function<Promise>} call
* @return {Function<Promise>}
*/
wrapCall(originalMethod, call){
if (this.synchronousCalls){
return () => Promise.resolve().then(call);
}
let actionName = this.constructor.name + "." + originalMethod.name;
return (...params) => {
return browser.runtime.sendMessage({
action: actionName,
params: [...params]
});
};
}
/**
* @param {string} someArgument
* @return {Promise<string>}
*/
someMethod(someArgument){
return this.wrapCall(this.someMethod, () => {
return Promise.resolve(`After all, I was evaluated on ${this.instanceName} with argument ${someArgument}`);
})(...arguments);
}
/**
* @param {string} someArgument
* @return {Promise<string>}
*/
someOtherMethod(someArgument){
return this.wrapCall(this.someOtherMethod, () => {
return `I'm another method. After all I was evaluated on ${this.instanceName} with argument ${someArgument}`;
})(...arguments);
}
}
starting BgCallExample background.js:9:3
After all, I was evaluated on x with argument test1 background.js:12:3
I'm another method. After all I was evaluated on x with argument test2 background.js:13:3
starting BgCallExample popup.js:6:3
After all, I was evaluated on x with argument test3 popup.js:10:3
I'm another method. After all I was evaluated on x with argument test4 popup.js:11:3
(async function test() {
console.log("starting BgCallExample from UI context");
let y = new BgCallExample(false, "y");
console.log(await y.someMethod("test3"));
console.log(await y.someOtherMethod("test4"));
})();
@phryneas
Copy link
Author

phryneas commented Jun 11, 2017

Also, note how someOtherMethod returns a string, but after wrapping it it is a Promise like everything else ;)
This is intentional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment