使用chrome.storage.sync.get返回undefined返回值

crz*_*777 8 javascript google-chrome-extension

我正在构建Chrome扩展程序,我编写了此代码.

var Options = function(){};

Options.prototype = {

    getMode: function(){
               return chrome.storage.sync.get("value", function(e){  
                 console.log(e); // it prints 'Object {value: "test"}'.       
                 return e;
               });
    },

    setMode: function(){
        chrome.storage.sync.set({"value": "test"}, function(e) {         
        })
    }
}

var options = new Options();
options.setMode();
console.log(options.getMode()); // it prints 'undefined'.
Run Code Online (Sandbox Code Playgroud)

我希望它能打印出来

Object {value: "set up"}
Run Code Online (Sandbox Code Playgroud)

我打电话的时候options.getMode(),打印出来undefined.

有谁知道如何解决这个问题?

Qan*_*avy 19

chrome.storageAPI是异步的 -它并不直接返回它,而是将它作为参数传递给回调函数.函数调用本身总是返回undefined.

这通常用于允许其他方法运行而不必等到某些响应或完成 - 这样的一个例子是setTimeout(唯一的区别是它返回一个计时器值,而不是undefined).

例如,拿这个:

setTimeout(function () { alert(1); }, 10000);
alert(0);
Run Code Online (Sandbox Code Playgroud)

因为setTimeout它是异步的,所以在整个函数完成之前它不会停止所有代码,而是最初返回,仅在稍后完成时调用函数 - 这就是为什么0在1之前出现的原因.


因此,您不能简单地执行以下操作:

// "foo" will always be undefined
var foo = asyncBar(function (e) { return e; }); 
Run Code Online (Sandbox Code Playgroud)

通常,您应该在回调中放置您想要做的事情(异步函数完成时调用的函数).这是编写异步代码的一种相当常见的方法:

function getValue(callback) {
  chrome.storage.sync.get("value", callback);
}
Run Code Online (Sandbox Code Playgroud)

您可以将整个代码部分放在回调中 - 没有什么可以阻止您这样做.所以不要做以下事情:

console.log(getValue()); // typical synchronous method of doing something
Run Code Online (Sandbox Code Playgroud)

这可能是一个更好的主意:

// how it would be done in asynchronous code
getValue(function (value) {
  console.log(value);
}); 
Run Code Online (Sandbox Code Playgroud)


Tao*_*lam 8

Chrome 存储 API是异步的,它使用callback,这就是您得到这种行为的原因。

您可以使用PromiseAPI 来克服这个异步问题,它更简单、更清晰。下面是一个例子:

async function getLocalStorageValue(key) {
    return new Promise((resolve, reject) => {
        try {
            chrome.storage.sync.get(key, function (value) {
                resolve(value);
            })
        }
        catch (ex) {
            reject(ex);
        }
    });
}

const result = await getLocalStorageValue("my-key");
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。对 Google 开发人员的一个尖锐评论:将 **async** 方法字面命名为 **sync** 是个好主意吗?谁能想到…… (2认同)