使用 extend-chrome/messages 从后台脚本向内容脚本发送消息时出错
Get error while using extend-chrome/messages while sending messgae from background script to content script
我正在使用 this 库进行消息传递。
我有这样的后台脚本
import { sendUrlInfo, waitForUrl } from 'utils/messaging';
import URL from 'url-parse';
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
sendUrlInfo(new URL(details.url));
});
chrome.webNavigation.onCompleted.addListener((details) => {
if (details.url !== 'about:blank') {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
sendUrlInfo(new URL(details.url));
}
});
根据文档,我 message.js 如下所示
import { getMessage } from '@extend-chrome/messages';
import URL from 'url-parse';
const messageTypes = {
URL_INFO: 'URL_INFO',
};
export const [sendUrlInfo, urlStream, waitForUrl] = getMessage<URL>(
messageTypes.URL_INFO,
);
现在是我用 React 编写的内容脚本
所以我试图在安装组件时订阅流
import React, { useState, useEffect, useRef } from 'react';
import Editor from 'content/components/Editor';
import Opener from 'content/components/Opener';
import { urlStream, waitForUrl } from 'utils/messaging';
const Main: React.FC = () => {
const [isOpen, setIsOpen] = useState(false);
const [showContent, setShowContent] = useState(false);
const editorRef = useRef<HTMLTextAreaElement | null>(null);
useEffect(() => {
console.log('MOunted');
urlStream.subscribe(([url]) => {
console.log('Received', url.hostname, url.pathname);
if (url.hostname === 'www.youtube.com' && url.pathname === '/watch') {
if (!showContent) setShowContent(true);
} else {
if (showContent) setShowContent(false);
}
});
}, []);
useEffect(() => {
document.addEventListener('keydown', onKeyPress);
return () => {
document.removeEventListener('keydown', onKeyPress);
};
});
const onKeyPress = (e: KeyboardEvent) => {
if (e.ctrlKey && e.which === 192) {
e.preventDefault();
setIsOpen(!isOpen);
}
};
if (!showContent) return <></>;
return (
<>
<div>test</div>
<Opener isOpen={isOpen} onClick={() => setIsOpen(true)} />
<Editor
isOpen={isOpen}
ref={editorRef}
onClose={() => setIsOpen(false)}
/>
</>
);
};
export default Main;
我在后台脚本控制台中遇到的错误是
Could not establish connection. Receiving end does not exist
据我所知,后台脚本正在尝试发送消息,但可观察到的内容脚本尚未订阅。作为页面加载后的内容脚本 运行。
如果这是问题所在,是否有任何方法可以正确使用此库。
顺便说一句,如果我们像这样使用普通 chrome api
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(
tabs[0].id,
message,
function () {
console.log("msg sent")
}
);
});
并使用 onMessage 接收消息。
后台页面需要知道我们正在向选项卡发送消息。除非定义 options.tabId
,否则 sendUrlInfo
使用 chrome.runtime.sendMessage
.
发送消息
在后台脚本中将选项参数添加到 sendUrlInfo
:
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
const options = { tabId: details.tabId }; // Add options.tabId here
sendUrlInfo(new URL(details.url), options);
});
我正在使用 this 库进行消息传递。
我有这样的后台脚本
import { sendUrlInfo, waitForUrl } from 'utils/messaging';
import URL from 'url-parse';
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
sendUrlInfo(new URL(details.url));
});
chrome.webNavigation.onCompleted.addListener((details) => {
if (details.url !== 'about:blank') {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
sendUrlInfo(new URL(details.url));
}
});
根据文档,我 message.js 如下所示
import { getMessage } from '@extend-chrome/messages';
import URL from 'url-parse';
const messageTypes = {
URL_INFO: 'URL_INFO',
};
export const [sendUrlInfo, urlStream, waitForUrl] = getMessage<URL>(
messageTypes.URL_INFO,
);
现在是我用 React 编写的内容脚本 所以我试图在安装组件时订阅流
import React, { useState, useEffect, useRef } from 'react';
import Editor from 'content/components/Editor';
import Opener from 'content/components/Opener';
import { urlStream, waitForUrl } from 'utils/messaging';
const Main: React.FC = () => {
const [isOpen, setIsOpen] = useState(false);
const [showContent, setShowContent] = useState(false);
const editorRef = useRef<HTMLTextAreaElement | null>(null);
useEffect(() => {
console.log('MOunted');
urlStream.subscribe(([url]) => {
console.log('Received', url.hostname, url.pathname);
if (url.hostname === 'www.youtube.com' && url.pathname === '/watch') {
if (!showContent) setShowContent(true);
} else {
if (showContent) setShowContent(false);
}
});
}, []);
useEffect(() => {
document.addEventListener('keydown', onKeyPress);
return () => {
document.removeEventListener('keydown', onKeyPress);
};
});
const onKeyPress = (e: KeyboardEvent) => {
if (e.ctrlKey && e.which === 192) {
e.preventDefault();
setIsOpen(!isOpen);
}
};
if (!showContent) return <></>;
return (
<>
<div>test</div>
<Opener isOpen={isOpen} onClick={() => setIsOpen(true)} />
<Editor
isOpen={isOpen}
ref={editorRef}
onClose={() => setIsOpen(false)}
/>
</>
);
};
export default Main;
我在后台脚本控制台中遇到的错误是
Could not establish connection. Receiving end does not exist
据我所知,后台脚本正在尝试发送消息,但可观察到的内容脚本尚未订阅。作为页面加载后的内容脚本 运行。 如果这是问题所在,是否有任何方法可以正确使用此库。
顺便说一句,如果我们像这样使用普通 chrome api
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(
tabs[0].id,
message,
function () {
console.log("msg sent")
}
);
});
并使用 onMessage 接收消息。
后台页面需要知道我们正在向选项卡发送消息。除非定义 options.tabId
,否则 sendUrlInfo
使用 chrome.runtime.sendMessage
.
在后台脚本中将选项参数添加到 sendUrlInfo
:
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
const url = new URL(details.url);
console.log('sending', url.hostname, url.pathname);
const options = { tabId: details.tabId }; // Add options.tabId here
sendUrlInfo(new URL(details.url), options);
});