我正在 React 中开发一个 Chrome 扩展,它在后台脚本上调用异步函数。为此,用户单击内容脚本上的按钮来触发此功能。脚本执行时,按钮会显示一个加载图标,并且应在后台脚本完成后恢复。我在扩展中使用 webext-redux 作为 Redux:https://github.com/tshaddix/webext-redux
我还没有让它正常工作,所以这里有一些伪代码,如果运行内容脚本的浏览器窗口保持打开状态,则可以工作
内容脚本
componentDidMount() {
chrome.runtime.onMessage.addListener(
(request) => {
if(request.action === "syncComplete") {
this.props.dispatch(syncing(false))
}
});
}
sync() {
this.props.dispatch(syncing(true));
chrome.runtime.sendMessage({action: "sync"});
}
render() {
<a onClick={() => this.sync()}>
{this.props.syncing ? (<span><Icon type="loading" /> Syncing...</span>) : "Force Sync" }
</a>
}
后台脚本
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if(request.action === "sync") startImport();
return true
});
async function startImport() {
...
// Large async function
// On complete or fail do:
chrome.tabs.query({url: "https://example.com/*"}, (tabs) => {
for (var i=0; i<tabs.length; ++i) {
chrome.tabs.sendMessage(tabs[i].id, {action: "syncComplete"});
}
});
}
我面临的问题是,由于我的异步函数在后台脚本中运行(故意这样用户可以继续在内容脚本所在的网站上导航),如果用户关闭内容脚本选项卡并且后台脚本完成,没有运行内容脚本来接收 Chrome 消息以调度同步操作。因此,整个扩展程序会陷入按钮上永久的“加载”状态。
有谁知道我该如何解决这个问题,或者是否可以从后台脚本调度一个动作?
关闭选项卡后,内容脚本实例也随之消失,并且无法再将操作从后台页面分派到该内容脚本。 (即使用户对该选项卡执行 Ctrl-Shift-T,它也会有一个新的选项卡。)
您提到您的扩展程序陷入“加载状态”。解决此问题的一种方法是在背景页面的
localStorage
中维护一个标志,例如 localStorage.hasPendingUpdate
。下次加载 example.com
选项卡时,向后台页面发送消息,询问是否有任何待处理的更新。如果有,后台页面会向该选项卡发送待处理的更新。
针对那些现在想要开始创建浏览器扩展并正在弄清楚如何构建合适的商店的人的个人经验说明。
不要使用 webext-redux!!!
这是“最简单”但不是最佳解决方案(因为我们为每个选项卡播放存储库)。现在它是一个糟糕的解决方案,因为它的支持很糟糕(最后一次更新是在两年前)。
您可以将 Chrome Storage API 作为解决方案。