Krejcir.6 Krejcir.6 - 1 month ago 8
Javascript Question

Code is executing multiple times per event: Multiple downloads

I want download JSON object from content script. At first, request to downloading, is download one file, but at second request, it is downloaded two files, at third request are download three files, etc.

Background.js



chrome.browserAction.onClicked.addListener(function (tab) {
download();
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
//Alert the message
console.log(request);
chrome.downloads.download({
url: request.method,
filename: request.name
}, function (downloadId) {

});
//You have to choose which part of the response you want to display
// ie. request.method
//alert('The message from the content script: ' + request.method);
//Construct & send a response
sendResponse({
response: "Message received"
});
});
});

function download() {
chrome.tabs.executeScript(null, {
file: "jquery.js"
}, function () {
chrome.tabs.executeScript(null, {
file: "content_script.js"
});
});
}


Content Script



function sendMessage(url, filename) {
//Construct & send message
chrome.runtime.sendMessage({
method: url,
name: filename
}, function (response) {
//Alert the message
//You have to choose which part of the response you want to display
// ie. response.response

//alert("The response from the background page: " + response.response);
});
}
var json = JSON.stringify(ticket);
var blob = new Blob([json], {
type: "application/json"
});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = "backup.json";
a.href = url;
a.textContent = "Download backup.json";
var container = document.getElementById('ticketDetail');
//container.appendChild(a);
var fName = ticket.date.replace(".", "_")
sendMessage(url, fName.replace(".", "_") + ".json");

Answer

As is usually the case with this pattern of problem, the issue is that you are adding multiple anonymous listeners to an event. Specifically, you are adding yet another chrome.runtime.onMessage listener each time the action_button is clicked. You need to add the listener only once.

The simple solution to this is to just add the chrome.runtime.onMessage once:

chrome.browserAction.onClicked.addListener(function (tab) {
    download();
});

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    //Alert the message
    console.log(request);
    chrome.downloads.download({
        url: request.method,
        filename: request.name
    }, function (downloadId) {
    });
    //You have to choose which part of the response you want to display 
    //  ie. request.method
    //alert('The message from the content script: ' + request.method);
    //Construct & send a response
    sendResponse({
        response: "Message received"
    });
});

function download() {
    chrome.tabs.executeScript(null, {
        file: "jquery.js"
    }, function () {
        chrome.tabs.executeScript(null, {
            file: "content_script.js"
        });
    });
}