13

私は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'.

印刷されると思っていた

Object {value: "set up"}

を呼び出すとoptions.getMode()、が印刷されundefinedます。

この問題を解決する方法を知っている人はいますか?

4

3 に答える 3

22

chrome.storageAPI は非同期です。直接返すのではなく、引数としてコールバック関数に渡します。関数呼び出し自体は常に を返しますundefined

これは、何かが応答または完了するまで待たずに他のメソッドを実行できるようにするためによく使用されます - これの例はsetTimeout(唯一の違いは、 ではなくタイマー値を返すことですundefined)。

たとえば、次のようにします。

setTimeout(function () { alert(1); }, 10000);
alert(0);

は非同期であるためsetTimeout、関数全体が完了するまですべてのコードを停止するのではなく、最初に戻り、後で完了するときにのみ関数を呼び出します。これが、0 が 1 の前に表示される理由です。


このため、単純に次のようなことを行うことはできません。

// "foo" will always be undefined
var foo = asyncBar(function (e) { return e; }); 

一般に、やりたいことはコールバック (非同期関数が完了したときに呼び出される関数) に入れる必要があります。これは、非同期コードを記述するかなり一般的な方法です。

function getValue(callback) {
  chrome.storage.sync.get("value", callback);
}

コード全体をコールバック内に配置することもできます。そうすることを妨げるものは何もありません。したがって、次のことを行う代わりに:

console.log(getValue()); // typical synchronous method of doing something

これはおそらくより良いアイデアでしょう:

// how it would be done in asynchronous code
getValue(function (value) {
  console.log(value);
}); 
于 2013-09-09T13:17:59.687 に答える
8

Chrome ストレージ APIは非同期であり、 を使用しcallbackているため、この動作が発生しています。

API を使用Promiseして、この非同期の問題を克服できます。これは、よりシンプルでクリーンです。次に例を示します。

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");
于 2019-08-19T06:19:06.607 に答える
2

chrome.storage.sync.get非同期で呼び出されるため、後で実行されるようにコールバックを渡す必要があります。

戻り値を印刷しようとすると、実行する非同期呼び出しをキューに入れた後に返さgetModeれるものの戻り値が印刷されます。chrome.storage.sync.get

これは、非同期呼び出しの使い方を学んでいるときに、JavaScript でよくある間違いです。

于 2013-09-09T13:18:07.180 に答える