【问题标题】:How to use async with other asynchronous modules?如何将 async 与其他异步模块一起使用?
【发布时间】:2014-06-18 05:28:41
【问题描述】:

这是一个没有异步的工作测试程序:

var fs = require('fs');
function test() {
    var finalResponse = '', response = '';
    function showFinalResponse() {
        console.log(finalResponse);
    }
    function processTheFile(err, data) {
        if (err) {
            finalResponse = 'Could not read the file';
        } else {
            response += data;
            response += '</body></html>';
            finalResponse = response;
        }
        showFinalResponse();
    }
    function readTheFile(exists) {
        if (!exists) {
            finalResponse = 'File does not exist.';
            showFinalResponse();
        } else {
            response += '<!DOCTYPE html><html lang="en-US"><head></head><body>';
            fs.readFile('file.txt', 'utf8', processTheFile);
        }
    }
    fs.exists('file.txt', readTheFile);
};
test();

这是我尝试让相同的程序与异步瀑布一起工作。我在如何在异步和 fs 调用中传递回调时遇到问题。

var fs = require('fs');
var async = require('async');
function testAsync() {var finalResponse, response = '';
    async.waterfall( [
        function checkIfTheFileExists(done) {
            fs.exists('file.txt', done);
        },
        function readTheFile(err, exists, done) {
            response += '<!DOCTYPE html><html lang="en-US"><head></head><body>';
            fs.readFile('file.txt', 'utf8', done);
        },
        function processTheFile(err, data, done) {
            response += data;
            response += '</body></html>';
            finalResponse = response;
            done(null);
        } ],
        function showFinalResponse(err) {
            if (err) {
                if (err.code === 'ENOENT') {  // intended to test for file is missing.
                    finalResponse = 'File does not exist.';
                } else { // any other errors.
                    finalResponse = 'Could not read the file';
                }
                console.log(err);
            }
            console.log(finalResponse);
        }
    );
}
testAsync()

我无法让异步版本工作。我对回调的去向感到困惑。

【问题讨论】:

    标签: javascript node.js asynchronous fs


    【解决方案1】:

    这是我的最终工作版本(以防它帮助其他人)。再次感谢您的帮助!

    var fs         = require('fs');
    var async      = require('async');
    var addErrParm = function (err, done) {return function(exists) {
        done(err, exists);
    }}
    function testAsync() {var finalResponse, response = '';
        function checkIfTheFileExists(done) {
            fs.exists('file.txt', addErrParm(null, done));
        }
        function readTheFile(exists, done) {
            if (!exists) {
                done('notFound');
            } else {
                response += '<!DOCTYPE html><html lang="en-US"><head></head><body>';
                fs.readFile('file.txt', 'utf8', done);
            }
        }
        function processTheFile(data, done) {
            response += (data || 'The file is empty') + '</body></html>';
            finalResponse = response;
            done(null);
        }
        function showFinalResponse(err) {
            if (err) {
                finalResponse = (err === 'notFound' ? 'File does not exist.' : 'Could not read the file');
            }
            console.log(finalResponse);
        }
        async.waterfall([ checkIfTheFileExists,
                          readTheFile,
                          processTheFile
        ], showFinalResponse);
    }
    testAsync()
    

    所以基本上,异步需要从除最终回调之外的所有函数中删除 err 参数(第一个参数),并且需要在除最终回调之外的所有函数上添加一个回调('done')作为额外参数。

    另外,如果没有像 fs.exists 这样的 err 参数,您必须创建一个函数来模拟 err 参数,以便 async 可以将其删除。

    【讨论】:

      【解决方案2】:

      fs.exists 很奇怪,因为它没有向其回调函数提供错误参数。相反,它只提供一个exists 参数来指示是否找到了文件。据推测,如果有错误,exists 将是false。因此,您需要将其回调包装在您自己的函数中,以便您可以为waterfall 回调提供单独的错误参数:

      async.waterfall( [
          function checkIfFileExists(done) {
              fs.exists('file.txt', function(exists) { done(null, exists); });
          },
          function makeSureFileExists(exists, done) {
          ...
      

      请注意 the docs 中的警告,但通常不应使用 fs.exists

      【讨论】:

      • 我确实看到了该警告,但我正在使用它,因为我不想在某些情况下打开文件。我只想知道它是否存在。
      • 请在下面的答案中查看我的最终版本。有什么问题吗?
      【解决方案3】:
      fs.exists('file.txt', done(null));
      

      这会立即调用done。您需要将实际的done 函数传递给fs.exists

      fs.exists('file.txt', done);
      

      其他人也一样。

      【讨论】:

      • @ChrisG.:fs.exists 接受回调,如果有错误则将其传递给错误,如果没有则将 null 传递给它。在回调之前你不知道是否有错误。传递done 与传递function (error, result) { done(error, result); } 是一回事。
      • @ChrisG.: processFileFile 也不会出错。这就是大多数异步函数的用途;如果瀑布的任何部分出现错误,只有最终的回调会得到它,而介于两者之间的将被跳过。
      • 好的,我认为正在取得进展。仍然无法正常工作。我编辑了问题以显示我最近的尝试。
      猜你喜欢
      • 2013-08-14
      • 1970-01-01
      • 2013-04-18
      • 2018-07-16
      • 2018-05-22
      • 2021-06-06
      • 2014-09-28
      相关资源
      最近更新 更多