使用async的Node.js - 如何在fs.readFile中正确使用async.forEachLimit?

时间:2021-12-24 18:58:57

I am developing a part of a Node.js application that needs to get version information from a specific points in various files. I have coded the functionality for this using the npm package, async.

我正在开发Node.js应用程序的一部分,该应用程序需要从各种文件中的特定点获取版本信息。我使用npm包async编写了这个功能。

I know exactly what my problem is. However, because I am so new to Node.js, and even newer to the async package, I am not implementing something right.

我确切地知道我的问题是什么。但是,因为我对Node.js这么新,甚至更新的异步包,我没有正确实现。

It seems that the contents of the version variable is not making it to my response in time. In other words, the response is being sent before the version can make it to the response.

似乎版本变量的内容没有及时响应我的响应。换句话说,响应是在版本进入响应之前发送的。

Below is the relevant code:

以下是相关代码:

exports.getAllVersionInformation = function(request, response) {
    if (!utilities.checkLogin(request, response))
        return;

    // Get the array of file information stored in the config.js file
    var fileCollection = config.versionsArray;

    // Declare the array to be used for the response
    var responseObjects = [];

    async.forEachLimit(fileCollection, 1, function(fileInformation, taskDone) {
        // Declare an object to be used within the response array
        var responseObject = new Object();

        // Retrieve all information particular to the given file
        var name = fileInformation[0];
        var fullPath = fileInformation[1];
        var lineNumber = fileInformation[2];
        var startIndex = fileInformation[3];
        var endIndex = fileInformation[4];

        // Get the version number in the file
        var version = getVersionInFile(fullPath, lineNumber, startIndex,
                endIndex, taskDone);

        console.log('Ran getVersionInFile()');

        // Set the name and version into an object
        responseObject.name = name;
        responseObject.version = version;

        // Put the object into the response array
        responseObjects.push(responseObject);

        console.log('Pushed an object onto the array');

    }, function(error) {
        console.log('Entered the final');

        if (error == null)
            // Respond with the JSON representation of the response array
            response.json(responseObjects);
        else
            console.log('There was an error: ' + error);
    });
};

function getVersionInFile(fullPath, lineNumber, startIndex, endIndex, taskDone) {
    console.log('Entered getVersionInFile()');
    var version = fs.readFile(fullPath,
            function(error, file) {
                if (error == null) {
                    console.log('Reading file...');

                    var lineArray = file.toString().split('\n');

                    version = lineArray[lineNumber].substring(startIndex,
                            endIndex + 1);
                    console.log('The file was read and the version was set');
                    taskDone();
                } else {
                    console.log('There was a problem with the file: ' + error);
                    version = null;
                    taskDone();
                }
            });
    console.log('Called taskDone(), returning...');
    return version;
};

I have tried playing with how the getVersionInFile function returns the data. I have moved the taskDone() function around to see if that would make a difference. I've asked Google so many questions about async and the way to use it in my context. I can't seem to get it working.

我试过玩getVersionInFile函数如何返回数据。我已经移动了taskDone()函数,看看是否会产生影响。我已经向谷歌询问了很多关于异步的问题以及在我的上下文中使用它的方法。我似乎无法让它发挥作用。

Some of the more important resources I have used are these: http://www.sebastianseilund.com/nodejs-async-in-practice http://book.mixu.net/node/ch7.html

我使用的一些更重要的资源是:http://www.sebastianseilund.com/nodejs-async-in-practice http://book.mixu.net/node/ch7.html

I added console.log statements to get a trace of the code flow. Here's the picture for that: 使用async的Node.js  - 如何在fs.readFile中正确使用async.forEachLimit?

我添加了console.log语句来获取代码流的跟踪。这是图片:

Additionally, I have part of the response I was expecting. Here's that as well: ![Browser Output]http://imgur.com/rKFq83y

另外,我有一些我期待的回应。这也是:[浏览器输出] http://imgur.com/rKFq83y

The issue with this output is that each object within the JSON should also have a version value. So, the JSON should look something like: [{"name":"WebSphere","version":"x.x.x.x"},{"name":"Cognos","version":"x.x.x.x"}]

此输出的问题是JSON中的每个对象也应具有版本值。因此,JSON应该类似于:[{“name”:“WebSphere”,“version”:“x.x.x.x”},{“name”:“Cognos”,“version”:“x.x.x.x”}]

How can I get my getVersionInFile() function to properly give me the version number in time? Also, how can I make sure I do this asynchronously without doing any blocking (hense the reason of using async for flow control)?

如何让我的getVersionInFile()函数及时正确地给我版本号?另外,如何在不进行任何阻塞的情况下确保异步执行此操作(因为流控制使用异步的原因)?

Any insight or suggestions would be greatly appreciated.

任何见解或建议将不胜感激。

1 个解决方案

#1


1  

One issue is that getVersionInFile() is returning a value before the asynchronous readFile() has finished (also being async, readFile() does not return a meaningful value). Also, using a limit/concurrency of 1 for forEachLimit() is the same as forEachSeries(). Here is an example that uses mapSeries() that should get you the same end result:

一个问题是getVersionInFile()在异步readFile()完成之前返回一个值(也是异步,readFile()不返回有意义的值)。此外,对forEachLimit()使用1的限制/并发性与forEachSeries()相同。这是一个使用mapSeries()的例子,它可以得到相同的最终结果:

exports.getAllVersionInformation = function(request, response) {
  if (!utilities.checkLogin(request, response))
    return;

  // Get the array of file information stored in the config.js file
  var fileCollection = config.versionsArray;

  async.mapSeries(fileCollection, function(fileInformation, callback) {
    // Retrieve all information particular to the given file
    var name = fileInformation[0];
    var fullPath = fileInformation[1];
    var lineNumber = fileInformation[2];
    var startIndex = fileInformation[3];
    var endIndex = fileInformation[4];

    // Get the version number in the file
    getVersionInFile(fullPath,
                     lineNumber,
                     startIndex,
                     endIndex,
                     function(error, version) {
      if (error)
        return callback(error);

      callback(null, { name: name, version: version });
    });
  }, function(error, responseObjects) {
    if (error)
      return console.log('There was an error: ' + error);

    // Respond with the JSON representation of the response array
    response.json(responseObjects);
  });
};

function getVersionInFile(fullPath, lineNumber, startIndex, endIndex, callback) {
  fs.readFile(fullPath,
              { encoding: 'utf8' },
              function(error, file) {
                if (error)
                  return callback(error);

                var lineArray = file.split('\n');

                version = lineArray[lineNumber].substring(startIndex,
                        endIndex + 1);
                callback(null, version);
              });
};

#1


1  

One issue is that getVersionInFile() is returning a value before the asynchronous readFile() has finished (also being async, readFile() does not return a meaningful value). Also, using a limit/concurrency of 1 for forEachLimit() is the same as forEachSeries(). Here is an example that uses mapSeries() that should get you the same end result:

一个问题是getVersionInFile()在异步readFile()完成之前返回一个值(也是异步,readFile()不返回有意义的值)。此外,对forEachLimit()使用1的限制/并发性与forEachSeries()相同。这是一个使用mapSeries()的例子,它可以得到相同的最终结果:

exports.getAllVersionInformation = function(request, response) {
  if (!utilities.checkLogin(request, response))
    return;

  // Get the array of file information stored in the config.js file
  var fileCollection = config.versionsArray;

  async.mapSeries(fileCollection, function(fileInformation, callback) {
    // Retrieve all information particular to the given file
    var name = fileInformation[0];
    var fullPath = fileInformation[1];
    var lineNumber = fileInformation[2];
    var startIndex = fileInformation[3];
    var endIndex = fileInformation[4];

    // Get the version number in the file
    getVersionInFile(fullPath,
                     lineNumber,
                     startIndex,
                     endIndex,
                     function(error, version) {
      if (error)
        return callback(error);

      callback(null, { name: name, version: version });
    });
  }, function(error, responseObjects) {
    if (error)
      return console.log('There was an error: ' + error);

    // Respond with the JSON representation of the response array
    response.json(responseObjects);
  });
};

function getVersionInFile(fullPath, lineNumber, startIndex, endIndex, callback) {
  fs.readFile(fullPath,
              { encoding: 'utf8' },
              function(error, file) {
                if (error)
                  return callback(error);

                var lineArray = file.split('\n');

                version = lineArray[lineNumber].substring(startIndex,
                        endIndex + 1);
                callback(null, version);
              });
};