Looping and asynchronous problems with node. js

Source: Internet
Author: User

The asynchronous mechanism of node. JS is implemented by events and callback functions, and it may feel like a violation of the routine at first, but the habit will find it simple. However, in fact, there are a lot of pitfalls, a very easy problem is the callback function in the loop, beginners often easy to fall into this trap. Let's start with an example to illustrate the problem.

    1. var fs = require (' FS ');
    2. var files = [' A.txt ', ' b.txt ', ' c.txt '];
    3. for (var i = 0; i < files.length; i++) {
    4. Fs.readfile (Files[i], ' utf-8 ', function (err, contents) {
    5. Console.log (Files[i] + ': ' + contents);
    6. });
    7. }

The function of this code is very intuitive, is to read the file a.txt, B.txt, c.txt, and output the file name and content. Assuming that the contents of these three files are AAA, BBB and CCC respectively, then the output we expect is:

A.txt:aaa

b.txt:bbb

C.txt:ccc

But what about the result of running this code? It turned out to be such a result:

Undefined:aaa

undefined:bbb

Undefined:ccc

This result shows that the file content is correctly output, and the filename is not correct, which means that the result of contents is correct, but the value of files[i] is undefined. How can this be, the file name is incorrect but can read the contents? Since it is difficult to understand intuitively, we will break down and print out the files[i, and output files, I, and files[i in the callback function of the read file respectively.

    1. var fs = require (' FS ');
    2. var files = [' A.txt ', ' b.txt ', ' c.txt '];
    3. for (var i = 0; i < files.length; i++) {
    4. Fs.readfile (Files[i], ' utf-8 ', function (err, contents) {
    5. Console.log (files);
    6. Console.log (i);
    7. Console.log (Files[i]);
    8. });
    9. }

Run the modified code with the following results:

[' A.txt ', ' b.txt ', ' c.txt ']

3

Undefined

[' A.txt ', ' b.txt ', ' c.txt ']

3

Undefined

[' A.txt ', ' b.txt ', ' c.txt ']

3

Undefined

Do you see a bit of inspiration here? The value of I for three outputs is 3, beyond the subscript range of the files array, so the value of files[i] is undefined. This usually occurs at the end of the for loop, such as for (var i = 0; i < files.length; i++), and the value of I is files.length when I exit the loop. Since the value of I is 3, it is true that the I value accessed in the Fs.readfile callback function is the result of a loop exit and cannot be distinguished. Files[i] As the first parameter of Fs.readfile is passed in the loop, so the file can be located, and can display the contents of the file.

Now the problem is clear: the reason is that the callback function that reads the file 3 times is actually the same instance where the I value referenced is the value after the end of the loop execution, and therefore cannot be distinguished. How to solve this problem? We can use

JavaScript functional programming features, manually set up a closure:

Forloopclosure.js

    1. var fs = require (' FS ');
    2. var files = [' A.txt ', ' b.txt ', ' c.txt '];
    3. for (var i = 0; i < files.length; i++) {
    4. (function (i) {
    5. Fs.readfile (Files[i], ' utf-8 ', function (err, contents) {
    6. Console.log (Files[i] + ': ' + contents);
    7. });
    8. }) (i);
    9. }

The above code establishes an anonymous function in the For loop body, passing and invoking the loop iteration variable i as a function parameter. Because of the existence of a runtime closure, the variables defined in the anonymous function (including the parameter table) are not freed until the function inside it (the Fs.readfile callback function) is executed, so the i we access here is a different closure instance, created during the execution of the loop body, Different values are preserved.

Add: The closure of the writing, there is no guarantee to the array of files in order to read the contents of the file, quite a number of file read operations in parallel, according to the size of the file to determine the speed of reading, and foreach can be guaranteed sequential read;

In fact, this kind of writing is not common, because it reduces the readability of the program, so it is not recommended to use. In most cases we can solve this problem using the array's ForEach method:

Callbackforeach.js

    1. var fs = require (' FS ');
    2. var files = [' A.txt ', ' b.txt ', ' c.txt '];
    3. Files.foreach (function (filename) {
    4. Fs.readfile (filename, ' utf-8 ', function (err, contents) {
    5. Console.log (filename + ': ' + contents);
    6. });
    7. });

Looping and asynchronous problems with node. js

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.