1

I'm making a Google Chrome extension. I'm trying to open new tabs and group them. I have urls as an array. But chrome.tabs.group function doesn't wait until all tabs open.

var ourTabIds = []
for(const url of urls) {
    chrome.tabs.create({active: false, url : url},tab => {
         ourTabIds.push(tab.id)
    })
}
chrome.tabs.group({tabIds : ourTabIds}, groupId => {console.log(groupId)})

The group function works when the ourTabIds is still empty. So it gives errors.

Why it doesn't wait? How can I fix that?

2

3 Answers 3

1

You could promisify chrome.tabs and then use Promise.all

function createTab(input){
   return new Promise(resolve => {
     chrome.tabs.create(input,tab => resolve(tab))
   });
}

and then you code becomes

(async function doIt(){
   var tabs = await Promise.all(urls.map(url => createTab({active: false, url : url})));

   chrome.tabs.group({tabIds : tabs.map(t => t.id)}, groupId => {console.log(groupId)})

})()
Sign up to request clarification or add additional context in comments.

4 Comments

It's more cool solution yes but I have to understand, normally when I write a loop, does not the code below the loop wait until the loop finish?
@I2mNew in your original code, no. Because the call you're making is asynchronous (see the link under your question someone posted). In this code, yes the 2nd line (the group line) waits for the first to complete
@I2mNew It does "wait" until the loop finishes. The thing is that your loop finishes long before your callbacks to the create method runs because chrome.tabs.create() is an asynchronous process. That's the whole reason it's using callbacks in the first place.
@Lennholm That's what I was trying to say, thanks for being more succinct than me.
0
var ourTabIds = [];
var countTabs = 0;
    for(const url of urls) {
            chrome.tabs.create({active: false, url : url},tab => {
                 ourTabIds.push(tab.id)
            countTabs++;
           if (countTabs==urls.length){
              chrome.tabs.group({tabIds : ourTabIds}, groupId => {console.log(groupId)})
            }
          })
        }
        

Comments

0

The function chrome.tabs.create() uses a callback as parameter. You should either convert that to Promises and finish it all with .then() or check if it is the last url (changing from of to in)

var ourTabIds = []
for(const index in urls) {
    chrome.tabs.create({active: false, url : urls[index]}, tab => {
         ourTabIds.push(tab.id)
         if (index === urls.length - 1 ) { // last url 
    //call when EVERYTHING has been pushed by the callback                 
chrome.tabs.group({tabIds : ourTabIds}, groupId => {console.log(groupId)}) 
             }
        })
    }

2 Comments

Yes this solution and the other solutions that use length of links works, thank you. But I can't understand why my first code doesn't wait?
It is not about waiting. It is not how callback works. See: developer.mozilla.org/en-US/docs/Glossary/Callback_function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.