Search code examples
javascriptgoogle-chrome-extensionfirefox-addon

chrome.windows.getAll() wait iterate and sendResponse


When user click on button this will send a message

// content script
    document.querySelector('#library').addEventListener('click', function (event) {
        
        chrome.runtime.sendMessage({type: "check if print"}, (response) => {
            console.log(response)
        });
        
    })
// background
    chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
        chrome.windows.getAll({}, function (windows_list) {
            windows_list.forEach(function (window) {
                if (window.type === "popup") {
// push array or sendResponse
                }
            })
        })
    })

I want to check if I have a popup and if I have a popUp, send a message to content script. But on console (content) it return a error

I had tried to populate a array, when message receive on background start a array and windows.getAll push array, and on after this check if my array has values send a response. Of course it sendMessage before getAll finish.

Unchecked runtime.lastError: The message port closed before a response was received.

On doc it says can use it with only queryParams and this will return a promise, but I only pass queryParams, I get error

// chrome documentation
getAll(queryOptions?: QueryOptions): Promise<object>
getAll(queryOptions?: QueryOptions, callback: function): void

// Error when I don't write callback
Uncaught TypeError: Error in invocation of tabs.query(object queryInfo, function callback): No matching signature.

Thanks,


Solution

  • You've written

    //push array or sendResponse

    sendResponse can be used only once to send-a-response.

    sendMessage doc says:

    Sends a single message to event listeners within your extension/app or a different extension/app. Similar to runtime.connect but only sends a single message, with an optional response.

    If you want to send only one response after chrome.windows.getAll iteration, you have to add return true as doc say here : https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessage

        chrome.windows.getAll({}, function (windows_list) {
            windows_list.forEach(function (window) {
                if (window.type === "popup") {
                   [...]
                }
            })
            //sendResponse
            return true
        })
    

    if your scenario foresee multiple popup windows, then you should think to another way as long-lived connections