0

I'm trying to figure out how to correctly use asynchronous functions for the purpose as described below.

<code>
async function commentGrabSwitchboard(){
  let prevStored = await checkStorage();
  if(IsAmazonFirstProductPage(document)){
    if(prevStored == undefined){
      collectProductComments();
    }else{
      console.log("Results retrieved from chrome local storage: \n" + JSON.parse(prevStored));
    }
  }
}
</code>

This function is designed as a switchboard. It does one of two things - either call collectProductComments or (for now) console log a result - dependant on the return value of the checkStorage function:

<code>
async function checkStorage(){
  let key = location.host + location.pathname;
  try{
    chrome.storage.local.get(key, function(result) {
        let returnData = result[key];
        return returnData;
    });
  }catch(err){
    console.log("Results for domain: " + key + "could not be retrieved from chrome local storage. Error: " + err);
  }
}
</code>

This function checks local storage for a value, and returns that value. If it should find nothing, the return value is undefined. The problem I am encountering is that the script does not wait for checkStorage to resolve after declaring the variable prevStored = checkStorage, and so the if statement "prevStored == undefined" is always true. I have verified that the checkStorage function does return the expected value from local storage.

Could anyone give me some pointers as to how I've done things incorrectly? Any alternative solutions are also welcome. Thanks.

temporary: changes to second function

function checkStorage(){
  let key = location.host + location.pathname;
  let storageSearched;
  let returnData;
  try{
    chrome.storage.local.get(key, function(result) {
        returnData = result[key];
        storageSearched = true;
    });
  }catch(err){
    console.log("Results for domain: " + key + "could not be retrieved from chrome local storage. Error: " + err);
    storageSearched = false;
  }
  let promise =  new Promise((resolve, reject) => {
    if(storageSearched){
      resolve(returnData);
    }else{
      reject();
    }
  });

  promise.then(function(fromResolve){
    return fromResolve;
  });
}
Ronno
  • 23
  • 8
  • You need to *promisify* the callback-based storage API and the easiest way to do that is to use [Mozilla's WebExtension polyfill](https://github.com/mozilla/webextension-polyfill). – wOxxOm Jan 29 '19 at 16:41

1 Answers1

1

Your first function is fine. The problem is with the second function.

Your first function is awaiting the second. You can only await a promise. The second function returns a promise. (So far as good).

The second function does not wait for chrome.storage.local.get before the promise resolves. It just gets to the end, has no return statement, and resolves the promise (created via the async keyword) as undefined.

So:

  • Remove the async keyword from the second function
  • Create a promise with new Promise() inside the second function
  • Return that promise
  • Resolve that promise with returnData instead of pointlessly returning returnData from the callback function.

Further reading: How do I convert an existing callback API to promises?

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Thanks very much for the detailed comment. I'm new to promises to I'm still struggling to figure out exactly how this works. I've put my amended second function in the question - it's definitely done incorrectly. Would you mind either showing me where I've gone wrong or pointing me in the direction of a resource to explain it? Ps. the first function remains the same. – Ronno Jan 29 '19 at 17:25
  • Simply use Mozilla's WebExtension polyfill and the modern async/await syntax as shown in the examples on the polyfill page. – wOxxOm Jan 31 '19 at 05:10
  • Thanks! I’ll take a look at this. – Ronno Jan 31 '19 at 13:23
  • @wOxxOm I've been trying to play around with the API you suggested, but due to my inexperience I do not know how to set up my manifest.json to support the use of it, hence the browser function is not defined. Do you know how to do this correctly? Do I have to add anything to my permissions? I read through the readme.md file and I see they've got an example of a manifest.json with "browser-polyfil.js" listed under the background/content scripts. Do I need to copy their browser-polyfil.js and place it in the same directory as my own scripts? Thanks very much for the help. Seriously appreciate it – Ronno Feb 01 '19 at 14:38
  • Yes. BTW you can see how it's done in any existing extension which should be easy to find in google search or in a similar site. – wOxxOm Feb 01 '19 at 14:45