gpt4 book ai didi

javascript - 返回没有功能的Chrome存储API值

转载 作者:行者123 更新时间:2023-12-03 08:17:14 25 4
gpt4 key购买 nike

在过去的两天里,我一直在使用chrome异步存储。如果您有功能,它可以“正常”运行。 (如下所示):

chrome.storage.sync.get({"disableautoplay": true}, function(e){
console.log(e.disableautoplay);
});

我的问题是我不能在执行的操作中使用函数。我想像LocalStorage一样返回它。就像是:
var a = chrome.storage.sync.get({"disableautoplay": true});

或者
var a = chrome.storage.sync.get({"disableautoplay": true}, function(e){
return e.disableautoplay;
});

我试过一百万种组合,甚至设置了一个公共(public)变量并设置为:
var a;
window.onload = function(){
chrome.storage.sync.get({"disableautoplay": true}, function(e){
a = e.disableautoplay;
});
}

没事。除非引用它的代码在get函数内部,否则所有返回的结果都是未定义的,这对我没有用。我只希望能够将值作为变量返回。

这有可能吗?

编辑:此问题不是重复的,请允许我解释原因:

1:没有其他帖子对此有具体要求(我花了两天时间才看清楚,以防万一)。

2:我的问题仍然没有得到回答。是的,Chrome存储空间是异步的,是的,它不返回任何值。那就是问题所在。我会在下面详细说明...

我需要能够在chrome.storage.sync.get函数之外获取存储的值。我无法使用localStorage,因为它是特定于url的,并且无法从chrome扩展程序的browser_action页面和background.js中访问相同的值。我不能用一个脚本存储值,而用另一个脚本访问它。他们被分开对待。

因此,我唯一的解决方案是使用Chrome存储。必须有某种方法来获取存储项的值并在get函数之外对其进行引用。我需要在if语句中检查它。

就像localStorage可以做什么
if(localStorage.getItem("disableautoplay") == true);

必须有某种方式来做一些事情
if(chrome.storage.sync.get("disableautoplay") == true);

我意识到这不会那么简单,但这是我能解释的最好方法。

我看到的每个帖子都说要这样做:
chrome.storage.sync.get({"disableautoplay": true, function(i){
console.log(i.disableautoplay);
//But the info is worthless to me inside this function.
});
//I need it outside this function.

最佳答案

这是针对您问题的量身定制的答案。为何仍有90%的解释说明为什么您无法绕过异步,但请多多包涵-它将总体上为您提供帮助。我保证最后会有与chrome.storage相关的东西。

在开始之前,我将重申以下规范链接:

  • After calling chrome.tabs.query, the results are not available
    (特定于Chrome,RobW的出色回答,可能最容易理解)
  • Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference(有关您所要要求的一般规范引用)
  • How do I return the response from an asynchronous call?
    (关于异步JS的一个较老但同样受人尊敬的规范问题)
  • You Don't Know JS: Async & Performance(关于JS异步性的电子书)

  • 因此,让我们讨论JS的异步性。

    第1节:什么?

    首先要介绍的概念是运行时环境。在某种程度上,JavaScript嵌入在另一个控制其执行流程的程序中-在本例中为Chrome。所有发生的事件(计时器,点击等)都来自运行时环境。 JavaScript代码注册事件的处理程序,这些事件在运行时会记住并在适当时调用。

    其次,重要的是要了解JavaScript是单线程的。运行时环境维护一个事件循环。如果事件发生时还有其他代码正在执行,则当当前代码终止时,将该事件放入队列以待处理

    看一下这段代码:
    var clicks = 0;

    someCode();
    element.addEventListener("click", function(e) {
    console.log("Oh hey, I'm clicked!");
    clicks += 1;
    });
    someMoreCode();

    那么,这里发生了什么?在执行此代码时,当执行到达.addEventListener时,将发生以下情况:,通知运行时环境,当事件发生(单击element)时,应调用处理程序函数。

    重要的是要了解(尽管在这种情况下很明显)该功能目前尚未运行。该事件仅在以后发生时才运行。一旦运行时确认“在发生这种情况时,我将运行(或“回调”,因此名称为“callback”),执行将继续。”如果someMoreCode()尝试访问clicks,则将是0,而不是1

    这就是所谓的异步性,因为这将在当前执行流程之外发生。

    第2节:为什么需要它,或者为什么同步API消失了?

    现在,重要的考虑因素。假设someMoreCode()实际上是一段运行时间很长的代码。如果点击事件仍在运行,该怎么办?

    JavaScript没有中断的概念。 运行时将看到正在执行代码,并将事件处理程序调用放入队列中。 someMoreCode()完全完成之前,处理程序将不会执行。

    尽管单击事件处理程序在不能保证单击发生的意义上说是极端的,但这解释了为什么不能等待异步操作的结果。这是一个不起作用的示例:
    element.addEventListener("click", function(e) {
    console.log("Oh hey, I'm clicked!");
    clicks += 1;
    });
    while(1) {
    if(clicks > 0) {
    console.log("Oh, hey, we clicked indeed!");
    break;
    }
    }

    您可以单击一下内容,但是会增加clicks的代码正在耐心地等待(非终止)循环终止。哎呀。

    请注意,这段代码不仅会冻结这段代码:我们等待时不再处理每个事件,因为只有一个事件队列/线程。 JavaScript中只有一种方法可以让其他处理程序执行其工作:终止当前代码,并让运行时知道发生我们想要的操作时要调用的内容。

    这就是为什么将异步处理应用于另一类调用的原因:
  • 需要运行时(而不是JS)来执行某些操作(例如,磁盘/网络访问)
  • 确保终止(无论成功还是失败)

  • 让我们来看一个经典的例子:AJAX调用。假设我们要从URL加载文件。
  • 假设在当前连接上,运行时可以以100ms内可在JS中使用的格式请求,下载和处理文件。
  • 在另一个连接上,情况更糟,它将花费500毫秒。
  • 有时连接确实很差,因此运行时将等待1000ms并放弃超时。

  • 如果我们要等到此完成,就会有可变的,不可预测的且相对较长的延迟。由于JS等待的工作方式,所有其他处理程序(例如UI)都不会在此延迟时间内完成工作,从而导致页面冻结。

    听起来很熟悉?是的,这正是同步XMLHttpRequest的工作原理。它实际上发生在运行时代码中,而不是JS代码中的while(1)循环-因为JavaScript在等待时无法让其他代码执行。

    是的,这允许使用熟悉的代码形式:
    var file = get("http://example.com/cat_video.mp4");

    但是,一切冻结的代价是巨大的,这是可怕的。 如此可怕的代价,以至于事实上,现代的浏览器都认为它已经过时了。 这是discussion on the topic on MDN

    现在让我们看看localStorage。它与“终止对运行时的调用”的描述相匹配,但是它是同步的。为什么?

    简而言之:历史原因(这是一个非常古老的规范)。

    虽然肯定比网络请求更可预测,但是localStorage仍然需要以下链:

    JS code <-> Runtime <-> Storage DB <-> Cache <-> File storage on disk

    这是一个复杂的事件链,因此需要暂停整个JS引擎。这导致what is considered unacceptable performance

    现在,Chrome API完全是为提高性能而设计的。您仍然可以在较早的API中看到一些同步调用,例如chrome.extension,并且有些调用是在JS中处理的(因此可以理解为同步),但是chrome.storage是(相对)新的。

    因此,如果在运行时执行某项操作存在延迟,则将它embraces the paradigm "I acknowledge your call and will be back with results, now do something useful meanwhile"发出。与XMLHttpRequest不同,这些调用没有同步版本。

    引用文档:

    It's [chrome.storage] asynchronous with bulk read and write operations, and therefore faster than the blocking and serial localStorage API.



    第3节:如何接受异步性?

    处理异步性的经典方法是回调链。

    假设您具有以下同步代码:
    var result = doSomething();
    doSomethingElse(result);

    假设现在doSomething是异步的。然后变成:
    doSomething(function(result) {
    doSomethingElse(result);
    });

    但是,如果更复杂呢?说是:
    function doABunchOfThings() {
    var intermediate = doSomething();
    return doSomethingElse(intermediate);
    }

    if (doABunchOfThings() == 42) {
    andNowForSomethingCompletelyDifferent()
    }

    好吧..在这种情况下,您需要在回调中移动所有这些内容。 return必须改为成为调用。
    function doABunchOfThings(callback) {
    doSomething(function(intermediate) {
    callback(doSomethingElse(intermediate));
    });
    }

    doABunchOfThings(function(result) {
    if (result == 42) {
    andNowForSomethingCompletelyDifferent();
    }
    });

    在这里,您有一连串的回调:doABunchOfThings立即调用doSomething,该调用将终止,但稍后有时会调用doSomethingElse,其结果通过另一个回调反馈给if

    显然,这种分层可能会变得凌乱。 好吧,没有人说JavaScript是一种好语言。

    有一些工具使其更易于管理,例如Callback HellPromises。我不会在这里讨论它们(用完了空间),但是它们不会改 rebase 本的“此代码只会在以后运行”部分。

    TL; DR节:我绝对必须使存储同步,暂停!

    有时出于合理的原因拥有同步存储。例如,async API阻止调用无法等待。否则,回调 hell 将使您付出高昂的代价。

    您可以做的是拥有异步await的同步缓存。它会带来一些成本,但这并非不可能。

    考虑:
    var storageCache = {};
    chrome.storage.sync.get(null, function(data) {
    storageCache = data;
    // Now you have a synchronous snapshot!
    });
    // Not HERE, though, not until "inner" code runs

    如果您可以将所有初始化代码都放在一个函数webRequest中,那么您将拥有:
    var storageCache = {};
    chrome.storage.sync.get(null, function(data) {
    storageCache = data;
    init(); // All your code is contained here, or executes later that this
    });

    通过执行chrome.storage中的时间代码,以及在之后,当在init()中分配给处理程序的任何事件发生时,都将被填充。您已将异步性降低为ONE回调。

    当然,这只是执行init()时存储外观的快照。如果要保持存储的一致性,则需要通过 init() / storageCache 设置对get()的更新。由于JS的单事件循环性质,这意味着仅在您的代码不运行时才更新缓存,但是在许多情况下这是可以接受的。

    同样,如果您想将对storageCache的更改传播到实际存储中,仅设置chrome.storage.onChanged是不够的。您将需要编写storageCache填充程序,然后将两者都写入storageCache['key']并安排(异步)set(key, value)

    实现这些作为练习。

    关于javascript - 返回没有功能的Chrome存储API值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38425751/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com