nosh
nosh

Reputation: 692

How to wait for asynchronous chrome.storage.local.get() to finish before continuing execution

I have two calls to chrome.storage.local.get(). I need for these calls to finish before continuing executing the rest of the code (calling continueCode() function) for my chrome extension, but I'm not sure how to do this, here is my code.

function getData() {
    chrome.storage.local.get(['key'], function(result) {
        if (Object.values(result)[0] != undefined) {
            object1.innerHTML = Object.values(result)[0].val;
        }
    });

    chrome.storage.local.get(['key2'], function(result) {
         if (Object.values(result)[0] != undefined) {
             object2.innerHTML = Object.values(result)[0].val;
         }
    });

    continueCode();
}

Upvotes: 14

Views: 18128

Answers (4)

Anurag Chatterjee
Anurag Chatterjee

Reputation: 11

Here is a simplified answer to achieve this if you can change getData() to async:

async function getData() {
    var result = await chrome.storage.local.get('key');
    if (Object.values(result)[0] != undefined) {
        object1.innerHTML = Object.values(result)[0].val;
    }

    result = await chrome.storage.local.get('key2')
    if (Object.values(result)[0] != undefined) {
         object2.innerHTML = Object.values(result)[0].val;
    }

    continueCode();
}

The important part is you can simply await the result.

result = await chrome.storage.local.get(key);

Note: You can get both data from key1 and key2 in one call by passing them together in the array.

Upvotes: 1

Jeff Baker
Jeff Baker

Reputation: 1502

https://developer.chrome.com/docs/extensions/reference/storage/#asynchronous-preload-from-storage has an example of getting chrome storage asynchronously. They use the following function. (I modified it to be able to return any top keys)

function getAllStorageSyncData(top_key) {
  // Immediately return a promise and start asynchronous work
  return new Promise((resolve, reject) => {
    // Asynchronously fetch all data from storage.sync.
    chrome.storage.local.get(top_key, (items) => {
      // Pass any observed errors down the promise chain.
      if (chrome.runtime.lastError) {
        return reject(chrome.runtime.lastError);
      }
      // Pass the data retrieved from storage down the promise chain.
      resolve(items);
    });
  });
}

// It can be called like this:
var obj = await getAllStorageSyncData(['key','key2']);
// obj will have obj.key and obj.key2

Put null as the top key to return all keys.

Upvotes: 0

Toan Quoc Ho
Toan Quoc Ho

Reputation: 3378

You can use new Promise, async/await to handle this. Let's say that you want to handle chrome.storage.local.get synchronously so that continueCode() can has the needed data.

Get data:

  const readLocalStorage = async (key) => {
    return new Promise((resolve, reject) => {
      chrome.storage.local.get([key], function (result) {
        if (result[key] === undefined) {
          reject();
        } else {
          resolve(result[key]);
        }
      });
    });
  };

Main function:


async function getData() {
    let key1 = await readLocalStorage('key1');
    object1.innerHTML = key1;
    let key2 = await readLocalStorage('key1');
    object1.innerHTML = key2;

    continueCode();
}

or if you're not familiar with async/await behavior. You could wrap those 2 promises into an array and use Promise.all, like so:

function getData() {
    const key1 = readLocalStorage('key1');
    const key2 = readLocalStorage('key2');

    Promise.all([key1, key2]).then(values => {
        object1.innerHTML = values[0];
        object2.innerHTML = values[1];

        continueCode();
    });
}

Upvotes: 36

Titus
Titus

Reputation: 22484

You need to wait for both callback function that you pass to chrome.storage.local.get(..) to be executed before you call continueCode(), also, you can check both storage properties with a single call, here is an example:

function getData() {
  chrome.storage.local.get(['key', 'key2'], function(result) {
    if (typeof result.key !== 'undefined') {
      object1.innerHTML = result.key.val;
    } 
    if (typeof result.key2 !== 'undefined') {
      object2.innerHTML = result.key2.val;
    } 
    continueCode();
  }
}

Upvotes: -2

Related Questions