3

I am building my first chrome extension, which creates a playlist of links by grabbing urls from a webpage. However, I am getting hung up on my messaging function. I've written a test function called 'test' inside my playlist object, and I am simply trying to assign the message that the content script is sending back (via the getPageInfo function) to a variable in my object function. However, though I am getting a message back, the string is getting lost between the return statement and the test function. Here's my background script:

//BACKGROUND.JS

var Playlist = {
index: 0,
playlist: [],
test: function(info) {
    var message = "Get Song";
    var song = getPageInfo(message);
    alert(song); //Shows undefined
    }
};

function getPageInfo(message) {
var s;
chrome.tabs.query({active:true, currentWindow:true}, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, {greeting: message}, function(response){
            console.log(response.farewell);
            s = response.farewell;
            alert(s); //Shows "We did it" 
        });
    });
alert(s) //Shows "We did it"
return s;
}

chrome.contextMenus.create({
title: "Add to Playlist",
contexts: ["image", "link", "selection"],
onclick: Playlist.test
});

And here's my content script:

//CONTENT.JS

chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
    console.log(sender.tab ?
        "from a content script:" + sender.tab.url :
        "from the extension");
    if(request.greeting == "Get Song")
        sendResponse({farewell: "We did it"}); //My message
});

And here's my manifest:

{
"manifest_version": 2,

"name": "RedditDJ",
"description": "This app hides jobs which the user has already clicked on.",
"version": "1.0",
"content_scripts": [
    {
        "matches": ["http://www.reddit.com/*","https://www.reddit.com/*"],
        "js": ["script/jquery-2.1.4.js", "script/content.js"]
    }
],
"permissions": [
    "http://www.reddit.com/",
    "https://www.reddit.com/",
    "http://www.youtube.com/",
    "https://www.youtube.com/",
    "http://www.soundcloud.com/",
    "https://www.soundcloud.com/",
    "http://*/", 
    "https://*/",
    "tabs",
    "contextMenus",
    "storage"
],
"browser_action": {
    "default_icon": {
        "19":"style/img/icon_19.png",
        "38":"style/img/icon_38.png",
        "128":"style/img/icon_128.png"
    },
    "default_title": "Reddit DJ",
    "default_popup": "popup.html"
},
"background": {
    "scripts": ["script/background.js"],
    "persistent": true
}
}

I've been turning it over for a couple of days, but I can't figure out what I'm doing wrong. Any ideas? Thanks!

  • It's not "getting lost". All chrome.* API is asynchronous. You might want to read something on asynchronous code in js. Possible duplicate: [How to return the response from an asynchronous call?](http://stackoverflow.com/q/14220321) – wOxxOm Oct 27 '15 at 14:57

1 Answers1

0

You just can't transform asynchronous function to synchronous. You have to add callback parameter for getPageInfo and use it to returning value.

Something like this:

function getPageInfo(message, callback) {
    chrome.tabs.query({active:true, currentWindow:true}, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, {greeting: message}, function(response) {
            console.log(response.farewell);
            s = response.farewell;
            callback(s);
        });
    });
}

Or even better would be using promises:

function getPageInfo(message) {
    return new Promise(function(resolve, reject) {
        chrome.tabs.query({active:true, currentWindow:true}, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {greeting: message}, function(response) {
                console.log(response.farewell);
                s = response.farewell;
                resolve(s);
            });
        });
    });
}


getPageInfo().then(function(value) {
    alert(value);
})
Valentin Shergin
  • 7,166
  • 2
  • 50
  • 53