By samy


2012-07-27 12:53:47 8 Comments

I'm creating (learning) an extension for Google Chrome.

To debug some code, I inserted console.log(), as follows:

var fourmTabs = new Array();
chrome.tabs.query({}, function (tabs) {
    for (var i = 0; i < tabs.length; i++) {
        fourmTabs[i] = tabs[i];
    }
});
for (var i = 0; i < fourmTabs.length; i++) {
    if (fourmTabs[i] != null)
        window.console.log(fourmTabs[i].url);
    else {
        window.console.log("??" + i);
    }
}

It's very simple code: get all tabs info into an array of my own, and print some things.

To check whether the code works as it should, I run the code. Here comes the problem:

  • When I use breakpoints (via the Developer tools), the code runs fine.
  • Without breakpoints, nothing is printed.

Any idea why?

1 comments

@Rob W 2012-07-27 14:23:52

Your problem can be simplified to:

/*1.*/ var fourmTabs = [];
/*2.*/ chrome.tabs.query({}, function(tabs) {
/*3.*/     fourmTabs[0] = tabs[0];
/*4.*/ });
/*5.*/ console.log(fourmTabs[0]);

You expect that the fourmTabs array is updated (by line 3) when line 5 is reached.
That is wrong, because the chrome.tabs.query method is asynchronous.


In an attempt to make you understand the significance of the asynchronous aspect, I show a code snippet with the same structure as your code and a story.

/*1.*/ var rope = null;
/*2.*/ requestRope(function(receivedRope) {
/*3.*/     rope = receivedRope;
/*4.*/ });
/*5.*/ grab(rope);
  • At line 1, the presence of a rope is announced.
  • At lines 2-4, a callback function is created, which ought to be called by the requestRope function.
  • At line 5, you're going to grab the rope via the grab function.

When requestRope is implemented synchronously, there's no problem:
  You: "Hi, I want a rope. Please throw the rope"call the callback function" when you've got one."
  She: "Sure." throws rope
  You: Jumps and grabs rope - You manage to get at the other side, alive.

When requestRope is implemented asynchronously, you may have a problem if you treat it as synchronous:
  You: "Please throw a rope at me."
  She: "Sure. Let's have a look..."
  You: Jumps and attempts to grab rope Because there's no rope, you fall and die.
  She: Throws rope Too late, of course.


Now you've seen the difference between an asynchronously and synchronously implemented function, let's solve your original question:

var fourmTabs = new Array();
chrome.tabs.query({}, function (tabs) {
    for (var i = 0; i < tabs.length; i++) {
        fourmTabs[i] = tabs[i];
    }
    // Moved code inside the callback handler
    for (var i = 0; i < fourmTabs.length; i++) {
        if (fourmTabs[i] != null)
           window.console.log(fourmTabs[i].url);
        else {
            window.console.log("??" + i);
        }
    }
});
// <moved code inside callback function of chrome.tabs.query>

With breakpoints, your code works, because by the time that the second part of the code is reached, the callback has already been called.

@samy 2012-07-27 14:37:38

wow! thank u!.now, i understand that i need to wait, befor getting the data into my arry. the rope example is great but, can u show me (if is not so hard) how will u make sure she will throw me the rope befor i jump into my death?

@Rob W 2012-07-27 14:41:29

@samy Simply jump after receiving the rope. The "jump logic" has to be appended to the callback function. I've added the code for your case at the end of the answer, I hope that you understand it now :)

@samy 2012-07-27 14:44:22

ohhhh, i see the diffrence now. now i understnad! thank u very much!! for taking the time and making me understand this topic :)

@Adi 2012-07-29 15:23:06

This answer is legendary!

@doniyor 2014-08-10 23:31:06

one of the best answers on Stackoverflow.

@Dionys 2014-10-10 07:56:11

even 2 years latter that answer still is legend... wait for it ... dary

@GregB 2014-11-17 15:12:08

How can asynchronous code like this be changed to be more DRY? Let's say this extension uses an array of open tabs in several places. What patterns should be used to make asynchronous code reusable?

@Rob W 2014-11-17 15:16:02

@GregB Callbacks or promises.

@Marco Bonelli 2015-01-08 01:49:27

grab(rope) is definitely the best way to explain the difference between synchronous and asynchronous functions. Ingenious.

@James Cushing 2015-04-02 08:47:44

Best analogy for synch vs asynch ever.

Related Questions

Sponsored Content

6 Answered Questions

28 Answered Questions

[SOLVED] Short circuit Array.forEach like calling break

  • 2010-04-14 21:57:31
  • Scott Klarenbach
  • 932026 View
  • 1421 Score
  • 28 Answer
  • Tags:   javascript arrays

31 Answered Questions

[SOLVED] How to manage a redirect request after a jQuery Ajax call

12 Answered Questions

[SOLVED] Stop setInterval call in JavaScript

36 Answered Questions

[SOLVED] How do I return the response from an asynchronous call?

21 Answered Questions

[SOLVED] What is the difference between call and apply?

8 Answered Questions

12 Answered Questions

4 Answered Questions

Sponsored Content