如何在chrome扩展中存储数据/结果,以及如何使用setTimeout使其只被调用一次
How to store data/result in in chrome extension and how to use use of setTimeout so that it will be called only once?
我有一个chrome扩展,我想在其中运行一个webgl演示特定的时间,然后获得该页面的每秒帧数,然后加载一个新的webgl演示,然后存储每秒帧数,并在4-5个webgl的演示中继续此操作,并将结果存储为pass和frames per second,如果没有加载演示,则存储为fail。
我使用setTimeout在特定时间内运行,然后清除它以停止第一个演示并加载第二个演示。但在我的扩展中,它一直在加载第二个,无法清除第二个演示的Timeout并转到第三个。有人能帮我找到正确的方法吗?
background.js
//var duration = 30;
//var start_time = new Date();
var frames_per_demo = {};
var URL_1 = "http://david.alloza.eu/WebGL/morphing.html";
var URL_2 = "http://webglsamples.org/blob/blob.html";
var URL_3 = "http://webglsamples.org/dynamic-cubemap/dynamic-cubemap.html"
chrome.browserAction.onClicked.addListener(function(activeTab){
chrome.tabs.create({ url: URL_1 });
});
chrome.runtime.onMessage.addListener(function(msg, sender) {
if (msg.message === "TC_1") {
window.clearTimeout(msg.timer_1);
frames_per_demo.TC1_Result = msg.frames_1;
window.alert("tc1 " + JSON.stringify(frames_per_demo));
chrome.tabs.update({ url: URL_2 });
}
if (msg.message === "TC_2") {
window.clearTimeout(msg.timer_2);
frames_per_demo.TC2_Result = msg.frames_2;
window.alert("tc2 " + JSON.stringify(frames_per_demo));
chrome.tabs.update({ url: URL_3 });
}
if (msg.message === "TC_3") {
window.clearTimeout(msg.timer_3);
frames_per_demo.TC3_Result = msg.frames_3;
window.alert("tc3 " + JSON.stringify(frames_per_demo));
}
});
content.js:-
console.log("content script started");
var tc1_timer = setTimeout(function(){
console.log("Starting morphing demo");
var frames_morphing_demo = document.getElementById("framerate").innerHTML;
chrome.runtime.sendMessage({"message": "TC_1", "frames_1": frames_morphing_demo, "timer_1": tc1_timer});
}, 10000);
var tc2_timer = setTimeout(function(){
console.log("Starting blob");
var frames_blob_demo = document.getElementById("fps").innerHTML;
chrome.runtime.sendMessage({"message": "TC_2", "frames_2": frames_blob_demo, "timer_2": tc2_timer});
}, 20000);
var tc3_timer = setTimeout(function(){
console.log("Starting cubemap");
var frames_cubemap_demo = document.getElementById("fps").innerHTML;
chrome.runtime.sendMessage({"message": "TC_3", "frames_3": frames_cubemap_demo, "timer_3": tc3_timer});
}, 30000);
manifest.json
{
"name": "store FPS data",
"version": "1",
"browser_action":
{
"default_icon": "Test.png"
},
"background":{
"scripts": ["background.js"],
"persistent": true
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": false
}
],
"permissions": ["tabs", "storage"],
"manifest_version": 2
}
整个想法是一个接一个地运行所有演示,如果任何演示没有正确加载,则显示/存储失败,否则通过和FPS数据。有人能帮忙吗?
无论何时导航(例如,使用chrome.tabs.update({ url: URL_2 });
,但每次导航都会发生这种情况),附加到页面的JS上下文都会被完全删除。您的内容脚本无法保存。
因此,您的内容脚本只是重新启动(因为它是在导航后重新注入的)。此外,计时器不会在页面之间共享,因此您不能从后台取消计时器。
此外,由于它被设置为加载到的每一页,它使浏览不可用:
- 如果任何页面碰巧有
#framerate
或#fps
元素,它将向您的扩展发出信号,选项卡将被劫持 - 如果一个页面没有这样的元素,那么您的脚本在尝试访问
null.innerHTML
时就会失败,并出现致命错误
一个好的策略是将状态保持在后台页面本身,并以编程方式注入脚本,而不是到处注入。
因此:
1) 从清单中删除内容脚本部分,并将测试的URL添加到"permissions"
(注入时需要)。顺便说一下,您不需要"tabs"
权限。
2) 制作一个适用于两个页面的通用脚本:
setTimeout(function(){
var fps_element = document.getElementById("framerate") ||
document.getElementById("fps");
if(fps_element) {
var fps = fps_element.innerHTML;
chrome.runtime.sendMessage(
{"message": "FPS", "frames": fps});
} else {
// No such element found; fail somehow
}
}, 10000);
3) 跟踪状态并根据需要在后台注入脚本:
var test = 0;
chrome.browserAction.onClicked.addListener(function(activeTab){
if(test == 0) { // Only react if test is not running yet
chrome.tabs.create({ url: URL_1 }, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "content.js"});
});
test = 1;
}
});
chrome.runtime.onMessage.addListener(function(msg, sender) {
if (msg.message === "FPS") {
switch(test) {
case 1:
frames_per_demo.TC1_Result = msg.frames;
// You really shouldn't use `alert`, since it blocks execution;
// Try chrome.notifications? Or use console for debugging.
alert("tc1 " + JSON.stringify(frames_per_demo));
test = 2;
chrome.tabs.update(sender.tab.id, { url: URL_2 }, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "content.js"});
});
break;
case 2:
frames_per_demo.TC2_Result = msg.frames;
alert("tc2 " + JSON.stringify(frames_per_demo));
test = 3;
chrome.tabs.update(sender.tab.id, { url: URL_3 }, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "content.js"});
});
break;
case 3:
frames_per_demo.TC3_Result = msg.frames;
alert("tc3 " + JSON.stringify(frames_per_demo));
test = 0;
chrome.tabs.remove(sender.tab.id);
break;
default:
// Unexpected, fail somehow
}
}
});
我留下了你使用的结构代码;如果您切换到使用URL和测试结果的数组,switch
可以被抛出以获得更好的代码。
失败留给读者练习。
case 1:
// Try chrome.notifications? Or use console for debugging.
frames_per_demo.TC1_Result = msg.frames;
//alert("tc1 " + JSON.stringify(frames_per_demo));
test = 2;
chrome.tabs.update(sender.tab.id, { url: URL_2 }, function(tab) {
**setTimeout(function(){
chrome.tabs.executeScript(tab.id, {file: "content.js"});},10000);**
});
break;
- 如何在chrome扩展中存储数据/结果,以及如何使用setTimeout使其只被调用一次
- 在setTimeout中调用相同的函数
- 为什么setTimeout适用于无休止的递归调用
- settimeout调用的函数未结束
- 调用setTimeout内部的函数时发生引用错误
- setTimeout调用自身的任何问题
- 如何将参数传递给使用 setTimeout 调用的函数
- 使用 setTimeout 调用一次 forEach 的回调函数即可完成
- 从setTimeout调用window.event时失败
- 函数(从setTimeout调用)未返回值
- 与连续的setTimeout调用相比,setInterval更有可能按时发生
- setTimeout调用的顺序
- 在setTimeout调用期间超过的最大调用堆栈大小
- 使用setTimeout调用函数,并提供可选的停止方式
- 无用的setTimeout调用(参数周围缺少引号?)
- 为什么这个setTimeout()调用在控制台中工作,而不是作为一个油脂猴子脚本
- 为什么通过setTimeout调用原型函数时会丢失实例信息?
- 如何从匿名函数中对同一函数进行 setTimeout 调用
- 错误:无用的setTimeout调用(参数周围缺少引号?)
- 如何在 setTimeout 调用中解决超出范围的 Var