如何在 chrome 扩展中设置全局变量

How can I set global variables in chrome extension

我开发了一个 chrome 扩展,它有一个在 background.js 的第一行中设置的 const 用户,当我更改它的值并稍后在不同的函数中使用它们时,它们总是return到他们开始时的设定值。

我在网上阅读了有关提升的信息,它是问题的根源,但我该如何避免它,这样我才能实际操作变量并在以后使用它们而不会出现问题。

我也看到了 globalThis 的使用,但是当我尝试使用 globalThis 调用或设置函数中的值时,它也不起作用。

这是我的第一行 background.js:

var user={
connection:undefined,
id:"id",
username:"username",
room:["id","password","url","tabid","ishost"],
room_members:[],
in_room:false,
room_process:[false,"intervelId"],
current_tab:["url","id"]

}

我还尝试使用 globalThis 设置一些用户值,如下所示:

function connect(){
   globalThis.user.connection = new WebSocket('ws://192.168.3.16:8765'); 
   globalThis.user.connection.onopen = function(e) {
     globalThis.user.connection.send("get_id");
   };
   globalThis.user.connection.onmessage=function(event){
      let data=event.data.split(',');
    
      let temp_i=data[0]
      globalThis.user.id=temp_i;

      let temp_u=data[1]
      globalThis.user.username=temp_u;
    
    console.log("connection: ",user.id,",",user.username);
   };    
   
}

例如,如果我从上一个函数中得到 user.id="Oak",当我尝试在另一个函数中调用值时,如下所示:

function test(){
   console.log(user.id);
}

它显示“id”而不是“Oak”

编辑

我尝试通过将 var user 放入程序的 onInstalled 事件中来使用 storage.local 然后通过两个函数我可以从本地存储中获取用户的当前值然后更新它还有。

这是我的代码:

var 用户的第一个初始化:

chrome.runtime.onInstalled.addListener(async () => {
//opens welcome page
let url = chrome.runtime.getURL("htmls/hello.html");

let tab = await chrome.tabs.create({ url });

//setting up the user var in chrome's local storage

chrome.storage.local.get(['userLocal'], async function (result) {

    var user={
        connection:undefined,
        id:"id",
        username:"username",
        room:["id","password","url","tabid","ishost"],
        room_members:[],
        in_room:false,
        room_process:[false,"intervelId"],
        current_tab:["url","id"]
        }
    chrome.storage.local.set({userLocal: user}, function () {}); // save it in local.
    
});

//connect to server and recive id 
connect()

});

两个函数函数:

function get_user(){
chrome.storage.local.get(['userLocal'], async function (result) {
    var userLocal = result.userLocal;
    return userLocal;
});

}

function update_user(tmp_user){
chrome.storage.local.get(['userLocal'], async function (result) {
    var userLocal = tmp_user;
    chrome.storage.local.set({userLocal: userLocal}, function () {}); // save it in local.
    return userLocal;
});  

}

例如,如果我使用我写的内容:

function connect(){

var user=get_user();

user.connection = new WebSocket('ws://192.168.3.16:8765'); //'ws://192.168.3.16:8765'
user=update_user(user);

}

我收到此错误:“未捕获(承诺)TypeError:无法设置未定义的属性(设置 'connection')”

问题是 background service worker 在需要时加载,空闲时卸载。因此,在闲置几秒钟后,后台脚本会自行卸载,使您丢失对用户对象所做的更改。

您可以将用户对象保存在 chrome.storage.local 中,然后从那里读取和修改。像这样:

// background.js; "initial lines" =>

chrome.storage.local.get(['userLocal'], async function (result) {
let userLocal = result.userLocal
if (userLocal === undefined) {
    // it means there was nothing before. This way you don't overwrite
    // the user object every time the backgorund.js loads.
    var user={
        connection:undefined,
        id:"id",
        username:"username",
        room:["id","password","url","tabid","ishost"],
        room_members:[],
        in_room:false,
        room_process:[false,"intervelId"],
        current_tab:["url","id"]
        }
    chrome.storage.local.set({userLocal: user}, function () {}); // save it in local.
}})

当你想修改用户时,你从本地检索它并修改结果,然后再将其保存回localStorage

// example of modifying a property =>

chrome.storage.local.get(['userLocal'], async function (result) {
let userLocal = result.userLocal
if (userLocal !== undefined) {
    userLocal.connection = new WebSocket('ws://192.168.3.16:8765');
    // ...

    chrome.storage.local.set({userLocal: userLocal}, function () {}); // save it in local.
}})

您也可以只读取用户属性,而不修改它们并将它们保存回 localStorage

############ 编辑:

因为chrome.storage.local是异步的,尝试像这样转换你的代码:

async function get_user(){
    return new Promise(async function (res, rej) {
      chrome.storage.local.get(['userLocal'], async function (result) {
          var userLocal = result.userLocal;
          res(userLocal);
      });
    });
}

var user= await get_user(); // call it like this.