sloker antonov
sloker antonov

Reputation: 13

Chrome extension - How to return a promise value from executed script in callback

Background.js:

chrome.tabs.executeScript(tab.id, 
{
    file: "exec_script.js"
}, function(res) {
    console.log(res);
});

exec_script.js:

var test = html2canvas(document.body, {
  allowTaint: false,
  letterRendering: true,
  logging: true
}).then(function (canvas) {
    var dataUrl = canvas.toDataURL();
    var bImage = dataUrl.replace('data:image/png;base64,', '');
});
test

As far as I know, the last statement in exec_script.js have to be passed to the callback as the result parameter. But it returns empty object.

But if I make as following in exec_script.js:

var test = "good";
test

It returns a value of the variable to the callback.

Also the tab is not focused.

Upvotes: 0

Views: 1386

Answers (1)

woxxom
woxxom

Reputation: 73616

The result returned by chrome.tabs.executeScript is produced by the main body of the executed script, in other words it is the standard behavior of synchronous JavaScript.

In your case the synchronous part creates test object, schedules a Promise but doesn't execute it yet (a task/microtask is queued), puts the just initialized test object as the last statement so that it gets picked up by executeScript. Furthermore, since executeScript transfers only JSON-ifiable portion of objects, and test being a complex class object, an empty object is transferred. You can check it manually by inspecting console.log(JSON.stringify(test)) in the console.

To transfer the results of asynchronous code use messaging:

  • background.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        console.log(sender.tab, msg);
        // do something
    });
    chrome.tabs.executeScript(tab.id, {file: "exec_script.js"});
    
  • exec_script.js

    var test = html2canvas(document.body, {
      allowTaint: false,
      letterRendering: true,
      logging: true
    }).then(function(canvas) {
        var dataUrl = canvas.toDataURL();
        var bImage = dataUrl.replace('data:image/png;base64,', '');
        chrome.runtime.sendMessage({dataUrl: dataUrl});
    });
    

N.B. only JSON-ifiable portion of objects is transferred via messaging.

Upvotes: 1

Related Questions