最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is the 'foreach' loop here behaving in parallel or squential? - Stack Overflow

programmeradmin2浏览0评论

I am new to javascript and I am trying to debug this piece of code, I was given in my class

fs.readdir('.', function(err, filenames) {
  if (err) throw err;
  console.log("Number of Directory Entries:", filenames.length)
  filenames.forEach(function (name) {
    fs.stat(name, function(err, stats) {
      if (err) throw err;
      total += stats.size;
    });
  });
});

I would like to know what is the program flow of the for-each will be? Will be in parallel or sequential? The instructor said that it is parallel, however from what I have read on the web,it seems it is sequential.

Is there anyway, I can tell by debugging like in java?

I am new to javascript and I am trying to debug this piece of code, I was given in my class

fs.readdir('.', function(err, filenames) {
  if (err) throw err;
  console.log("Number of Directory Entries:", filenames.length)
  filenames.forEach(function (name) {
    fs.stat(name, function(err, stats) {
      if (err) throw err;
      total += stats.size;
    });
  });
});

I would like to know what is the program flow of the for-each will be? Will be in parallel or sequential? The instructor said that it is parallel, however from what I have read on the web,it seems it is sequential.

Is there anyway, I can tell by debugging like in java?

Share Improve this question asked Dec 9, 2015 at 4:17 SahilSahil 9,50627 gold badges81 silver badges117 bronze badges 7
  • 3 forEach itself is not async so it is normally sequential. However fs.stat is async which will make it parallel. To be VERY percise, forEach runs sequentially to call fs.stat but fs.stat returns immediately and does nothing. AFTER the forEach has pleted all the fs.stat calls will run in parallel and be processed sequentially depending on which of them plete first. – slebetman Commented Dec 9, 2015 at 4:21
  • @slebetman - You should make that an answer. – Justin Niessner Commented Dec 9, 2015 at 4:22
  • the for loop is sequential but the fs.stat is in parallel. This is different from java in the sense that java is multithreaded and javascript is single threaded. It is an event based language. – dmcqu314 Commented Dec 9, 2015 at 4:22
  • can you please tell me which ide are you using? – Rana Ahmer Yasin Commented Dec 9, 2015 at 4:23
  • 1 Anyone who want free points feel free to make my ment an answer :) – slebetman Commented Dec 9, 2015 at 4:23
 |  Show 2 more ments

2 Answers 2

Reset to default 3

You have a little bit of both. The .forEach() loop is sequential (synchronous), but the fs.stat() call inside of it is asynchronous so all the fs.stat() calls will be in-flight at the same time (e.g. in parallel). So, this is what that means in a little more detail:

The .forEach() call will run immediately, starting all your fs.stat() calls. But, because they are async, they will just get started in the .forEach() loop. Then, sometime AFTER the .forEach() loop finishes when the system has finished each disk action, the fs.stat() callbacks will all get called.

The only place that you will actually know what the total variable ends up with is in the last fs.stat() callback that gets called. The way you've written your code, you can't reliably know when that is because the fs.stat() calls are not guaranteed to finish in any particular order.

You could see what the grand total is by keep track of when the last callback is called by using a counter with something like this:

fs.readdir('.', function(err, filenames) {
  if (err) throw err;
  console.log("Number of Directory Entries:", filenames.length)
  var doneCnt = 0;
  filenames.forEach(function (name) {
    fs.stat(name, function(err, stats) {
      ++doneCnt;
      if (err) throw err;
      total += stats.size;
      if (doneCnt === filesnames.length) {
          // all callbacks have pleted now
          console.log("Final total is: " + total);
      }
    });
  });
});

And, FYI it does no good to do throw err inside the fs.stat() or fs.readdir() callback. That exception just goes back into the asynchronous fs.readdir() or fs.stat() infrastructure and does not go anywhere that you can catch it or will even see it. You will likely need better error handling than what you have (this is where promises are so much better at handling async errors).


If you wanted to understand the sequencing of things, you could put some console.log() statements in and watch what order they get executed:

fs.readdir('.', function(err, filenames) {
  if (err) throw err;
  console.log("Number of Directory Entries:", filenames.length)
  var doneCnt = 0;
  filenames.forEach(function (name, index) {
    console.log("forEach: " + index);
    fs.stat(name, function(err, stats) {
      console.log("fsStat: " + index);
      ++doneCnt;
      if (err) throw err;
      total += stats.size;
      if (doneCnt === filesnames.length) {
          // all callbacks have pleted now
          console.log("Final total is: " + total);
      }
    });
  });
});

If there were 5 filenames, what you would see in the log would be something like this:

forEach: 0
forEach: 1
forEach: 2
forEach: 3
forEach: 4
fsStat: 0
fsStat: 1
fsStat: 2
fsStat: 3
fsStat: 4
Final total is: 57684

In fact, the fsStat callbacks are not guaranteed to get called in any particular order among themselves, but they are guaranteed to be AFTER all the forEach log statements.

I'm not a master in JS, I think the basic principle to run parallels function is iterate some call of a asynchronous function. (Ajax for example) and I don't think that's the case, right? So, it's sequencial.

发布评论

评论列表(0)

  1. 暂无评论