MozillaWebExtensionneneneba API存储-带断点和不带断点的调试会导致不同的输出

Mozilla WebExtension API storage - Debugging with and without breakpoints leads to different output

本文关键字:断点 输出 调试 存储 MozillaWebExtensionneneneba API      更新时间:2023-09-26


大家好,
我正在尝试为Mozilla Firefox浏览器实现一个附加组件。下面的脚本显示了我已经成功集成的一个backgorund脚本。它使用Mozilla WebExtension API存储。它被执行了,但浏览器控制台上的日志让我大吃一惊。我得到交替记录什么和:

bla
bla
bla

如果并且只有当我在调试模式下在代码的重要行(尤其是最后5行(上设置断点时,我总能得到预期的结果:

bla

输出如何依赖于设置断点。我不知道发生了什么,在互联网上也找不到类似的问题。有人能向我解释发生了什么,以及我能做些什么来防止错误的输出吗

storeManager.js:

var localStore = chrome.storage.local;  
var StoreManager = function(){};
StoreManager.prototype.addItem = function(type, item){
    var thisRef = this;
    localStore.get(type, 
        function(obj){
            if(chrome.runtime.lasterror){
                console.log(chrome.runtime.lastError);
            }else{
                var oldArr = obj[type];
                if(oldArr === undefined)
                    oldArr = [];
                if(oldArr.indexOf(item) !== -1)
                    return;
                oldArr.push(item);
                thisRef.setItem(type, oldArr);
            }
        }
    );
}
StoreManager.prototype.removeItem = function(type, item){
    var thisRef = this;
    localStore.get(type, 
        function(obj){
            if(chrome.runtime.lasterror){
                console.log(chrome.runtime.lastError);
            }else{
                var oldArr = obj[type];
                if(oldArr === undefined)
                    return;
                var index = oldArr.indexOf(item);
                if(index === -1)
                    return;
                oldArr.splice(index, 1);
                thisRef.setItem(type, oldArr);
            }   
        }
    );
}
StoreManager.prototype.setItem = function(type, item){
    localStore.set({ [type] : item }, 
        function(){
            if(chrome.runtime.lasterror){
                console.log(chrome.runtime.lastError);
            }
        }
    );
}
StoreManager.prototype.visitItems = function(type, visit){
    localStore.get(type, 
        function(obj){
            if(chrome.runtime.lasterror){
                console.log(chrome.runtime.lastError);
            }else{
                var oldArr = obj[type];
                if(oldArr !== undefined){
                    for(var i=0; i<oldArr.length; i++){
                        visit(oldArr[i]);
                    }
                }
            }
        }
    );
}
function justLog(str){
    console.log(str);
}
var sm = new StoreManager();
sm.visitItems("lol", justLog);
sm.addItem("lol", "bla");
sm.visitItems("lol", justLog);
sm.removeItem("lol", "bla");
sm.visitItems("lol", justLog);


manifest.json:

{
    "manifest_version": 2,
    "name": "Addon",
    "version": "0.0",
    "description": "no desc",
    "background": {
        "scripts": [
            "storeManager.js"
        ]
    },
    "permissions": [
        "storage"
    ]
}

storage.local.set()是异步的。在调用回调之前,数据不能保证对get()的调用可见(或者,如果使用browser.storage.localset()将返回Promise,并且数据将保证在Promise解析时写入(。

你的代码天生就充满了种族条件。对addItem()removeItem()的调用与对visitItems()的调用竞争,通过设置断点,您可以让一条路径或另一条路径"赢得"竞争。

如果您希望得到确定性的结果,我建议使用storage.local的Promise变体,并将代码编写为一系列链式处理程序。