How do I wait for a javascript function to return a response using Chrome.storage API?

google-chrome, google-chrome-extension, javascript, jquery

Solution

QF_D, I'm into educated guesswork here, so be prepared for this not to work first time .....

..... here goes :

if (!this.Chrome_getValue || (this.Chrome_getValue.toString && this.Chrome_getValue.toString().indexOf("not supported") > -1)) {
    this.Chrome_getValue = function (key, def) {
        var dfrd = $.Deferred();
        chrome.storage.local.get(key, function (result) {
            dfrd.resolve(result[key]);
        });
        return dfrd.promise();
    };
    this.Chrome_setValue = function (key, value) {
        var dfrd = $.Deferred();
        var obj = {};
        obj[key] = value;
        var listen = function(changes, namespace) {
            dfrd.resolve(changes[key]);
            chrome.storage.onChanged.removeListener(listen);//remove, to prevent accumulation of listeners
        }
        chrome.storage.onChanged.addListener(listen);
        chrome.storage.local.set(obj);
        return dfrd.promise()
    }
}

The get and set functions should thus return jQuery promises. The promise returned by the set function is resolved with a `StorageChange` object defined here. In general you won't need this object, rather just respond to the promise being resolved.

Everything above is untested. I'm not too sure about :

- `chrome.storage.onChanged....`. Should it be `chrome.storage.local.onChanged....`?

- `.removeListener()`. It seems resonable that it should exist if `addListener` exists, though I can't find any evidence of it.

Problem

I am trying to use the following code to set and get name value pairs in a Chrome Extension. ``` if (!this.Chrome_getValue || (this.Chrome_getValue.toString && this.Chrome_getValue.toString().indexOf("not supported") > -1)) { this.Chrome_getValue = function (key, def) { chrome.storage.local.get(key, function (result) { return result[key]; }); }; this.Chrome_setValue = function (key, value) { var obj = {}; obj[key] = value; return chrome.storage.local.set(obj) } } ``` I am then invoking these as follows: ``` Chrome_setValue("City", "London"); var keyValue = Chrome_getValue("City"); ``` The problem is the keyValue is always 'undefined' even if I put a 1 second delay in trying to read back the value. I understand this is because the 'chrome.storage.local.get' function is asynchronous.. the following code works fine. ``` Chrome_setValue("City", "London"); chrome.storage.local.get("City", function (result) { alert(result["City"]); }); ``` Is there any way when binding the keyValue (using `get`) I can force the code to wait for the function to return a response? Or perhaps I'm approaching this from the wrong angle. Essentially I am looking for a way I can abstract out the `set` and `get` methods for handling data within the chrome.storage framework? Ideally two simple functions I can call for setting and retrieving name value pairs. Before I was using localStorage which was very straightforward. ``` //Set localStorage["City"] = "London"; //Get var keyValue = localStorage["City"]; ```

Original source