0

I am attempting to use JavaScript promises so that the rest of my code waits for my asynchronous 'chrome.storage.local.get' call. However, it seems that the code is still acting asynchronously, and as a result sending undefined data out.

JavaScript code:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {

    if( request.message === "fetch-local-storage" ){//if popup request local data

        var responseData;

        let store = new Promise(function(resolve, reject){
            chrome.storage.local.get('localSearchList', function(query){
                responseData = query.localSearchList;
                resolve(responseData); // <- pass responseData to then()
            }); //fetch the local storage data 
        });

        store.then(function(responseData){ // <= response data will be avaialble in then, executing ONLY after the asych get call is executed
            sendResponse({message: "local-storage-data", data: JSON.stringify(responseData)});
        });

    }
 }

The console shows the following output:

The data being sent to popup (via content.js pipeline): undefined
asynch data: "[{\"word\":\"mo\",\"color\":\"rgb(128,0,128)\",\"id\":\"0\"}]"

If you look back at the code, this display shows that it is not working synchronously...

Aalok Borkar
  • 143
  • 2
  • 11
  • Add log for `responseData` in `store.then(function(responseData){` function and see what does it shows – Nikhil Aggarwal May 23 '18 at 06:24
  • The log right before the SendResponse shows that the data is perfectly fine.... – Aalok Borkar May 23 '18 at 06:28
  • 1
    Fixed it! Adding a return true; statement at the end of the addListener fixed the issue of sendResponse not working! – Aalok Borkar May 23 '18 at 06:32
  • Possible duplicate of [Chrome Extension Message passing: response not sent](https://stackoverflow.com/questions/20077487/chrome-extension-message-passing-response-not-sent) – wOxxOm May 23 '18 at 07:56

2 Answers2

1

You need to call resolve in the callback. The point of resolve is that it is called once the async operation is complete and the only way you know that is when the callback fires.

Additionally, you shouldn't be depending on an outside variable responseData you should pass this information into your resolve function where it will be available to then():

let store = new Promise(function(resolve, reject){
    chrome.storage.local.get('localSearchList', function(query){
        responseData = query.localSearchList;
        console.log("asynch data: " + JSON.stringify(responseData));
        resolve(responseData); // <- pass responseData to then()
    }); //fetch the local storage data 
});

store.then(function(responseData){ // <= response data will be avaialble in then
    console.log("The data being sent to popup (via content.js pipeline): " + JSON.stringify(responseData));
    sendResponse({message: "local-storage-data", data: JSON.stringify(responseData)});
});

This will fix the issue, but it's kind of overkill to create a promise here when you are just going to call then() on it. Why not put everything in the callback and save yourself the trouble?

  chrome.storage.local.get('localSearchList', function(query){
        responseData = query.localSearchList;
        console.log("The data being sent to popup (via content.js pipeline): " + JSON.stringify(responseData));
        sendResponse({message: "local-storage-data", data: JSON.stringify(responseData)});
        }); 

}

Mark
  • 74,559
  • 4
  • 81
  • 117
  • I cannot achieve the bottom code, because the sendResponse does not actually send a message if i put it in the local storage's methods' call back function. The sendResponse must be in the scope of the addListener which is at the top of the JS file (which i did not include) to execute correctly. – Aalok Borkar May 23 '18 at 05:59
  • With that said, your solution worked and I now realize that I must put the resolve inside the get function otherwise the get function's asynchonality will kick in and execute the resolve() statement, rendering the whole promise useless. – Aalok Borkar May 23 '18 at 06:01
-1

had the same issue , refer codes from this

You need to make use of async and await if i am not wrong , but in my case even that did not work out , so used it on state variable to correctly work / on page post back(I think it gets onto event loop and wait till the stack is empty to return back the data from fetch.then )

Sarav
  • 139
  • 13
  • If you look at the edits I made to the code, the sendMessage does not seem to be actually sending a message? Is it out of scope being nested inside a .then() statement? – Aalok Borkar May 23 '18 at 06:11
  • The problem here i think is use of your resolve , same problem as your in https://stackoverflow.com/questions/38397072/nodejs-then-function-executed-before-promise-resolve – Sarav May 23 '18 at 06:17