2

I have a page that should only load a certain portion if a setting is true. These settings are found in storage.

However I am unable to retrieve these settings when loading the page.
I have tried the following:

var permission = true;
chrome.storage.sync.get({ 
    history: true
}, function(items) {
    permission = items.history;
});

but permission will always equal true when the page loads. If I put a call to another function to print the value of permission, this will not be called until after.

I call this function as well as the functions loading the parts of the page using

document.addEventListener('DOMContentLoaded', function () {

I think the problem is that the function is not called in time, but I don't know how to resolve this.

Xan
  • 74,770
  • 16
  • 179
  • 206
user3542347
  • 39
  • 1
  • 6
  • Why not go more universal and just use HTML 5 localStorage? Is there a reason that you are using Chrome specific storage? That said, have you tried changing the placement of where you set the permission to true? For example, instantiate the empty var in the global scope, but set it to true inside a function ONLY if a specific condition is met (ie. the DOM completes loading, or maybe store the "true" state in storage and check for truthiness using that variable. If it is true, the new page loads. If not, return false. – Korgrue Jan 12 '16 at 22:42
  • I might try using HTML5. I'm new to this so I just went with the first one I saw. I've tried setting it as a global variable too, but the problem remains in that the value does not change until too late. – user3542347 Jan 12 '16 at 23:51
  • @Korgrue But localstorage doesn't sync. user3542347, is there a reason you cannot put the other functions inside the storage callback? – Daniel Herr Jan 12 '16 at 23:59
  • javascript memory is not persistent as you have experienced. Thankfully HTML5 brought us local and session storage that allows you to pass key:value pairs to other pages without having to query a database. In your case, I would do the check on the first page, then if the conditional is met, set a sessionStorage key to true and when the new page loads query that session key and if it is true, then update the necessary content. – Korgrue Jan 13 '16 at 00:01
  • @DanielHerr You are correct, but from what I gathered from user3542347 is that he just wants to store session vars and Chromes storage was the first thing he/she tried. I don't thing he/she is trying to sync data between machines - just pass data from one page to another. – Korgrue Jan 13 '16 at 00:06
  • @DanielHerr I did this for one or two, but if I ever wanted to call those functions again for whatever reason, the values would sometimes be incorrect. I was searching for a more permanent solution in case this situation arose again in a way that could not be solved the way you mentioned. – user3542347 Jan 13 '16 at 11:44
  • There is no need to be sorry about the duplicate: I'm just making sure that questions on the same (very common) topic all point to the canonical question with a lot more explanation. – Xan Jan 14 '16 at 15:29
  • @Xan Oh alright. I thought it was my fault if it is a duplicate. I did read through the duplicate link however and it was very useful, thanks. – user3542347 Jan 14 '16 at 19:55

1 Answers1

10

Your suspicion is correct. The callback after data is retrieved from storage will probably execute after page is loaded already.

To solve this, I suggest using Promise:

var p = new Promise(function (resolve, reject) {
    var permission = true;
    chrome.storage.sync.get({
        history: true
    }, function (items) {
        permission = items.history;
        resolve(permission);
    });
});
p.then(function (permission) {
    loadStuff(permission);
});

Rewritten with async/await, but we still have to promisify the callback:

async function getFromStorage(key) {
    return new Promise((resolve, reject) => {
        chrome.storage.sync.get(key, resolve);
    })
        .then(result => {
            if (key == null) return result;
            else return result[key];
        });
}

let permission = await getFromStorage("history");
Granga
  • 1,612
  • 1
  • 14
  • 20
  • 1
    Is there a major difference between doing it this way and simply putting the function calls inside the chrome.storage.sync.get function? Other than allowing for a "rejected" state? If the variable is made global and called elsewhere it will contain a different value on page load. – user3542347 Jan 13 '16 at 14:32
  • 1
    You are right, there is no difference. Maybe it's even better for your case to call the content loading function inside chrome.storage.sync.get callback. Can you clarify which variable you are talking about? – Granga Jan 13 '16 at 15:00
  • Sorry for the late response, I had just hoped that I could set a global "permission" variable that could be checked by multiple functions, but it seems I will need to just call each function from within the callback and pass in permission, or check inside each function. Thanks anyway. – user3542347 Jan 14 '16 at 14:30
  • This is just an aesthetic thing, but how would you refactor this with async/await? – feverdreme Jan 02 '21 at 03:59