0

I have a chrome extension that calls out to a server Back End. It works fine when I have the back end adress hardcoded into the code, but whilst trying to move that out into a user configurable setting it fails. The problem appears to be AJAX's async behaviour causing the issue because JQuery is sending off the AJAX 'GET' request before the code reaches into the Chrome Storage to get the current setting.

Within a Chrome Extension (popup.js) Using AJAX 3.5.1

The AJAX call is very simple:

    $.ajax({
    url: getCrumbURL(),   
    type: 'get',
    data: {},
    error: function(XMLHttpRequest, textStatus, errorThrown) { 
      console.log("Status: " + textStatus); 
      console.log("Error: " + errorThrown);}  ,
    success: function (data) {
          console.log(data);}});

and the getCrumbURL function is this:

  function getCrumbURL(){
var myBackend;
chrome.storage.sync.get({ "backEndServerURL": 'Not set yet' }, function (result) {
  myBackend = "http://" + result.backEndServerURL  + "crumbIssuer/api/json";
  console.log("1. Requesting crumb from: " + myBackend);          
})
console.log("2. Requesting crumb from: " + myBackend);
return myBackend; 

}

The AJAX function calls its own page (which I believe is the default if the url: is not set) so I think it's failing because it's not waiting for the call to chrome.storage.sync.get before trying to send the AJAX call. I suspect this because when I look at the output on the console, by two debus messages arrive in the reverse order:

I know AJAX is Async, but this is from WITHIN the AJAX call (as opposed to elsewhere in the code).

Can anyone explain whether my assumption is correct and whether there's a way to force the AJAX to wait for the chrome.storage.sync.get to return it's value (as it provides the URL!). Many thanks Matt

EDIT 1: I have read a number of SO questions that explain how to work with a response from an Aysnc call (for example using a Promise) but (and this may be my lack of experience) I cannot see how this applies here. The issue is not trying to do something AFTER an ASync call (the $.AJAX) but BEFORE it takes place (so that it has the URL pulled from the Chrome Storage). If I'm missing the answer in the other SO questions, please could someone help me out by explaining how this would work in the situation posted above? Many thanks.

Matt Lindsay
  • 45
  • 1
  • 9
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Robin Zigmond Jun 06 '20 at 19:18
  • Thanks Robin, but I don't **think** so. I've read that a few times but (and it may be my lack of experience) it relates to the response of an Async call, whereas I want to to ensure something is executed BEFORE the $.ajax call. If it does relate and I'm being slow, would you be able to show me how it would wotk with my situation? It looks like the Promise/Then approach is simplest but I can't get my head around how it would apply here. It boggles my mind that the `url:` parameter in the ajax all wouldn't wait for its dependency....? – Matt Lindsay Jun 06 '20 at 20:56
  • the problem is in `getCrumbURL`, in which the `chrome.storage.sync.get` function is (I assume) asynchronous. In which case - and this certainly seems to be what your `console.log` output suggests - `getCrumbURL` will always return `undefined` because you are returning `myBackend` from it before it has another value. [I've only just realised while typing this that the function actually has `sync` in its name, which does make it strange - but the fact it takes a callback makes me think it's actually async, and your experience here implies the same.] – Robin Zigmond Jun 06 '20 at 21:06
  • The 'sync' part in it refers to the type of Google Chrome storage (Local storage or 'sync'd) across devices, so it could be async. Is there a way I can ensure it populates the value before completing the function? – Matt Lindsay Jun 06 '20 at 22:39
  • Yes - which is exactly why I flagged the duplicate in the first place, as this is an absolutely standard question, with lots of answers on that thread :) Assuming the `chrome.storage.sync.get` returns a Promise (which I would hope it does but I haven't checked), you could either use `asnc/await`, or just return that promise from `getCrumbURL` and then use the result in your other function by calling it and then calling its `.then` method. – Robin Zigmond Jun 06 '20 at 22:41
  • Thanks. From [link](https://stackoverflow.com/questions/49847904/how-do-i-use-promise-all-with-chrome-storage) it would appear that the API doesn't support promises but the answer there helpfully provides an example for how to Promisify it. I've never used Promises (barely heard of them) but it looks like the way to go (albeit that I originally thought the issue was on the AJAX part, but now looks like it's the Chrome Storage part). It might be a while before I figure out and post the solution that worked (it seems I have some study to do on how to work with Promises) but I will! Thanks. – Matt Lindsay Jun 07 '20 at 12:15

0 Answers0