Question: How to use async properly to get chrome.storage?

I am creating a google chrome extension. On the popup, I am displaying a leaderboard. However, I am new to JavaScript so I don't know how to properly use async. I am using chrome.storage to get stored scores to display on the leaderboard, then sending them from background.js to score.js. My issue is that, since chrome.storage.get happens asynchronously, my findScores method does not wait for chrome.storage.get to finish before incorrectly returning a default empty score.
Here is my code:
background.js
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
      console.log(sender.tab ?
                  "from a content script:" + sender.tab.url :
                  "from the extension");
      if (request.type === "request") {
        var scoresVar = findScores(request.table, "All");
        console.log("Sending response " + scoresVar);
        sendResponse({scores: scoresVar})
      } 
      else if (request.type === "score") {
        saveScore(request.website, request.score, request.tab);
        sendResponse("Finished adding score " + request.score);
      }
    }
);

function findScores(table, website) {
    const categories = table.split("-");
    if (categories.includes("personal")) {
        chrome.storage.sync.get([website], function(response) {
            if (!(typeof response[website] === 'undefined')) {
                console.log("Found " + response[website]);
                return response[website];
            }
        });
    } else if (categories.includes("global")){
        // TODO: Add global leaderboards
        return ["-"];
    }
    console.log("Didn't find, on default");
    return ["-"];
}

popup.js
async function requestScores(tableID) {
  var url = "All"
  if (tableID.includes("current")) {
    var url = await getCurrentTab();
  }
  console.log("Sending message to load scores to " + url);
  (async () => {
    const response = await chrome.runtime.sendMessage({type: "request", request: "load scores", table: tableID, tab: url});
    console.log("Received: " + response);
    // add scores to HTML DOM
    });
  })();
}


My console messages reveal that I first return a default score, which is sent to popup.js. I have tried throwing async keywords in front of functions (as well as "await" in front of variables like scoresVar = await findScores(request.table, "All") but it just caused more issues, where findScores still returned a default value, but background.j instead sent an undefined promise.
How can I fix my code?


Answer:
It is simpler to work with Promises and async/await instead of callbacks. chrome.storage.sync.get returns a Promise if you do not pass a callback.
async function findScores(table, website) {
    // ...
    if (categories.includes("personal")) {
        const response = await chrome.storage.sync.get([website]);
        if (response[website] !== undefined) {
            console.log("Found " + response[website]);
            return response[website];
        }
    }
    // ...
}
// ...
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    // ...
    findScores(request.table, "All").then(scores => {
        console.log("Sending response " + scores);
        sendResponse({scores});
    });
    return true; // keep the messaging channel open for sendResponse
});

Note that the callback of onMessage should return a literal true value (documentation) in order to keep the internal messaging channel open so that sendResponse can work asynchronously.