2

My action in the background is to access the site and take information from there, the problem is that the code continues before the information is received. Attached is a code that shows the problem:

background.js :

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
fetch(request.input, request.init).then(function(response) {
    return response.text().then(function(text) {
        sendResponse([{
            body: text,
            status: response.status,
            statusText: response.statusText,
        }, null]);
    });
}, function(error) {
    sendResponse([null, error]);
    });
    return true;
});

actions.js : after editing

const validateWord = async word => {
const input = "https://milog.co.il/" + word;
await new Promise(resolve => {
    chrome.runtime.sendMessage({ input }, messageResponse => {
        const [response, error] = messageResponse;
        const parser = new DOMParser();
        const html = parser.parseFromString(response.body, 'text/html');
        const element = html.querySelector('.sr_e_txt');
        console.log("aaa")
        resolve(element?.innerText !== '');
    });
});
};

validateWord("word")
    .then(data => console.log(data))
        .catch(reason => console.log(reason.message))

it prints aaa -> bbb -> word.. I want the "word" printed first and "aaa" wait for it to finish.

Thank you.

Dor Swisa
  • 43
  • 1
  • 7
  • There's a [bug in Chrome](https://crbug.com/1197387): sendMessage doesn't return a Promise so you can't await it. You'll have to use a callback instead (you can use it to promisify the call so you'll be able to use await in the end). – wOxxOm Jul 12 '21 at 11:50
  • I dont understand how to use callback the code not waiting to the function.. – Dor Swisa Jul 12 '21 at 14:22

1 Answers1

4
  1. you can't use both a callback in a chrome method and await on the returned value because when a callback is used the method won't return a Promise.

  2. bug in Chrome before 99: sendMessage doesn't return a Promise so you can't await it.
    Fixed in Chrome 99.

So, in earlier versions of Chrome you can promisify the API:

promisifyApi(chrome.runtime, 'sendMessage');

(async () => {
  const res = await chrome.runtime.sendMessage({ input });
  console.log(res);
})();

function promisifyApi(thisArg, name) {
  const fn = thisArg[name];
  const localStack = new Error('Before calling ' + name);
  thisArg[name] = (...args) => new Promise((resolve, reject) => {
    fn(...args, result => {
      let err = chrome.runtime.lastError;
      if (err) {
        err = new Error(err.message);
        err.stack += '\n' + localStack.stack;
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}

...or use a callback:

chrome.runtime.sendMessage({ input }, res => {
  // process `res` here
});
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • I added your code, but I think again the function reads in parallel instead of the code waiting for it to end .. When I print the value that returns it prints undefined which from what I understand. the function still pending. – Dor Swisa Jul 12 '21 at 17:06
  • This is a standard case of promisfying so I guess you did something wrong. Can't help without seeing your exact code. – wOxxOm Jul 12 '21 at 17:40
  • first of all thank you very much.. I will edit my post. – Dor Swisa Jul 12 '21 at 19:16
  • I don't see where you print `bbb` and the word. – wOxxOm Jul 13 '21 at 02:09
  • I was able to fix, I had a syntax error .. Thanks a lot for the help. – Dor Swisa Jul 13 '21 at 13:36