Search code examples
javascriptgoogle-chrome-extension

Chrome extension: chrome local storage is not set instantly


I am having strange issues with Chrome Local storage setting and retrieval.

In background.js I am setting it when a certain URL's HTML is fetched once the page loading is completed and then in content.js I am fetching values from local storage. At times it is stored and fetched instantly while other times results.html is undefined. And if I use chrome.storage.local.clear() it makes it more worst, make you to refresh the page 2-3 times at least. Below is my code:

background.js

chrome.runtime.onMessage.addListener(
    async function(request, sender, sendResponse) {
        // Reset storage
        // chrome.storage.local.clear() // it is lagging refreshing values
        sendResponse("bar")
        // Check whether it is correct URL
        var url = 'http://localhost:8000/get.php?url='+request
        console.log('URL for AJAX =',url)
        var result = await sendReq(url)
        var json_result  = JSON.parse(result)
        var status = json_result['status'] 
        var rules = []
        console.log('Status = '+status)

        if(status == 'ok') {
            rules = json_result['msg']['rules']
            chrome.storage.local.set({'rules': rules}, function() {}); 
            
            url = 'http://localhost:8000/read.php?url='+request
            result = await sendReq(url)
            // console.log(result)
            chrome.storage.local.set({'html': result}, function() {}); // this goes undefined if the URL of visiting page is changed.
        } else {
            // To check on content script
            chrome.storage.local.set({'html': '__FAIL__'}, function() {}); 
        }
    }
);

content.js (Using JQuery)

  $(function() {
    // console.clear()
    console.log('The Agile Super Cluster extension cleared all previous output')
    chrome.storage.local.get(['html','rules'], function(result) {
        // Do not perform things below if it is not a relevant Super Cluster URL
        if(result.html == '__FAIL__' || typeof (result.html) == 'undefined') {
          return
        }
      .....

// Out of onReady() block
chrome.runtime.sendMessage(
        url,
        function (response) {
            console.log('Sending Response')
            console.log(response);
        }
    );

Solution

  • The solution is to use messaging correctly so you can wait on the result reliably.

    1. remove chrome.storage, it's not necessary for this task;
    2. remove async from onMessage listener (why?) and use a separate async function to get info;
    3. return the result via sendResponse + return true.

    content.js:

    chrome.runtime.sendMessage(url, res => {
      console.log(res);
      if (res.html) {
        // use `res.html` here
      }
    });
    

    background.js:

    const API_GET = 'http://localhost:8000/get.php?url=';
    const API_READ = 'http://localhost:8000/read.php?url=';
    
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
      getInfo(request).then(sendResponse);
      return true; // keep the channel open for asynchronous sendResponse
    });
    
    async function getInfo(url) {
      const res = JSON.parse(await sendReq(`${API_GET}${url}`));
      return res.status === 'ok' ? {
        rules: res.msg.rules,
        html: await sendReq(`${API_READ}${url}`),
      } : {};
    }