Skip to content

Instantly share code, notes, and snippets.

@salmin89
Last active June 12, 2025 09:37
Show Gist options
  • Save salmin89/5f523bc4994bdcec87605e126d9fff3f to your computer and use it in GitHub Desktop.
Save salmin89/5f523bc4994bdcec87605e126d9fff3f to your computer and use it in GitHub Desktop.
Chrome Messaging using Native Observables
declare const Observable: any;
// Utility to create an Observable from Chrome's messaging system
function createMessageObservable() {
return new Observable((subscriber: any) => {
// Set up the message listener
const listener = (message: any, sender: chrome.runtime.MessageSender, sendResponse: (response?: any) => void) => {
// Forward the message to the Observable
subscriber.next({ message, sender, sendResponse });
return true;
};
// Add the listener
chrome.runtime.onMessage.addListener(listener);
subscriber.addTeardown(() => {
console.log('Cleaning up message listener');
chrome.runtime.onMessage.removeListener(listener);
});
});
}
// Example usage in background script
const messageStream = createMessageObservable();
const controller = new AbortController();
// Subscribe to all messages
messageStream.subscribe(
{
next: ({ message, sender, sendResponse }: any) => {
if (message.type !== 'foo') {
return;
}
console.log('Processing message:', message);
// Example: Echo the message back with additional data
const response = {
received: true,
echo: message,
processedAt: Date.now(),
sender: sender.tab?.id,
};
sendResponse(response);
if (message.clicker > 2) {
// Cleanup after sending 3 responses
controller.abort();
}
},
error: (error: Error) => {
console.error('Error in message stream:', error);
},
},
{ signal: controller.signal }
);
messageStream.subscribe({
next: ({ message, sender, sendResponse }: any) => {
if (message.type !== 'bar') {
return;
}
console.log('Processing message:', message);
// Example: Echo the message back with additional data
const response = {
received: true,
echo: message,
processedAt: Date.now(),
sender: sender.tab?.id,
};
sendResponse(response);
// Cleanup after sending response
// controller.abort();
},
error: (error: Error) => {
console.error('Error in message stream:', error);
},
});
// Example: Send a message to the background script
function sendMessageToBackground(type: string, clicker: number) {
const message = {
type,
clicker,
data: 'Hello from content script!',
timestamp: Date.now(),
};
console.log('➡️ sending', message);
chrome.runtime.sendMessage(message).then((response: any) => {
console.log('⬅️ Received response from background:', response);
});
}
let clicker = 0;
// @ts-ignore
document.when('click').subscribe(() => {
clicker++;
sendMessageToBackground('foo', clicker);
});
// @ts-ignore
document.when('keydown').subscribe(() => {
sendMessageToBackground('bar', 0);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment