0

I used AJAX to get data that I named variable myPubscore. Now I'm trying to send myPubscore to another js file. myPubscore prints fine in Ajax, but when I print just before sendResponse, I get "Error in event handler: ReferenceError: myPubscore is not defined".

How do I get myPubscore out of AJAX and into sendResponse? I read through another SO post on this problem, but the respondents mentioned that the answer had depreciated.

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.type == "articleUrl") {
        console.log("background heard articleUrl")
        console.log(request);
        var articleUrl = request;
        $.ajax({
        type: 'POST',
        url: `${url}/buttoncolor`,
        data: articleUrl,
        success: function urlFunction(data) {
        var myPubscore = data;
        console.log("myPubscore in ajax:")
        console.log(myPubscore);
        }
        })
    console.log("myPubscore in sendresponce:")
    console.log(myPubscore);
    sendResponse({score: "myPubscore"});
    }

updated background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.type == "articleUrl") {
        console.log("background heard articleUrl")
        console.log(request);
        var articleUrl = request;
        $.ajax({
        type: 'POST',
        url: `${url}/buttoncolor`,
        data: articleUrl,
        success(data){
            console.log("incoming data");
            console.log(data);
            sendResponse(data);
            console.log("sent data");
            },
        });
        return true;
    }

content.js

        chrome.runtime.sendMessage({ "type": "articleUrl", "url": url }, function (response) {
            console.log("here's the response for sending the URL");
            console.log(response);
        });
codi6
  • 516
  • 1
  • 3
  • 18
  • You can't. It's asynchronous. You could wrap that entire Event in a `Promise` that resolves and passes data to it and use `promiseInstance.then(result=>{ /* now use result */ })`, but it's really just a syntax trick. – StackSlave May 14 '20 at 01:24

1 Answers1

2

When using an asynchronous call like $.ajax or fetch or XMLHttpRequest, its callback runs at a [much] later point in the future when the surrounding scope already ran so you need to use the results of the call inside the callback as explained in How do I return the response from an asynchronous call?

Important addition for extension messaging in Chrome

In Chrome, the onMessage API event won't recognize a Promise returned by the listener so to be able to use sendResponse asynchronously you need to return true from the onMessage listener and call sendResponse in the ajax callback:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'articleUrl') {
    $.ajax({
      url: '...........',
      success(data) {
        sendResponse(data);
      },
    });
    return true;
  }
});

or

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'articleUrl') {
    fetch('https://www.example.org').then(r => r.text()).then(sendResponse);
    return true;
  }
});

async keyword note

Note that you can't mark the onMessage listener with the async keyword when returning true because it would actually return a Promise object to the API, which is not supported in Chrome extensions API. In this case use a separate async function or an async IIFE, example.

P.S. If you use WebExtension polyfill you can return a Promise from the onMessage listener and use async function as a listener directly. In Firefox this is how the API works out-of-the-box.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • Thanks but I've been banned for asking this? I don't know how to improve the question. I guess because there already was a SO on it? I didn't know that when I asked, I didn't even know what async was when I asked. – codi6 May 14 '20 at 17:53
  • 1
    I don't know but maybe SO paused your ability to ask a question because the last few were duplicates. This is indeed unfriendly. I've unduped this question, see if you can post questions now. – wOxxOm May 14 '20 at 18:08
  • I can ask again! Thank you! I'm a beginner with no coding teachers, so not being able to use SO would be really disappointing. – codi6 May 14 '20 at 18:13