如何在javascript中的回调函数中为回调函数分配变量

时间:2017-07-13 14:47:36

标签: javascript node.js callback

所以我发现这个问题看起来非常相似,但我完全不理解答案我试图实现它,但我不认识我的代码中答案的模式。 similar question

现在这是我的问题,我有这段代码:

var fs = require('fs');
var index = JSON.parse(fs.readFileSync('../data/7XXX7/index.json', 'utf8'));
window = {};
var indicators = require('./indicators');
var parser = new window.patient.Indicator('tes', 'test');
var i = 0;

function create_indicators() {
    var result = [];
    fs.readdirSync('../data/7XXX7/files/').forEach(file => {
        fs.readFile('../data/7XXX7/files/' + file, 'utf8', function (err, data) {
            if (err)
                throw err;
            let $ = {};
            $.poids = parser.poids(data);
            $.taille = parser.taille(data);
            $.temperature = parser.temperature(data);
            $.tension = parser.tension(data);
            $.pouls = parser.pouls(data);
            $.ps = parser.ps(data);
            $.saturation = parser.saturation(data);
            for (var j in index.files)
            {
                if (index.files[j].name === file)
                {
                    $.id = index.files[j].name;
                    $.date = index.files[j].date;
                    $.name = index.files[j].IntituleSession;
                    break;
                }
            }
            if ($.poids || $.taille || $.temperature || $.tension || $.pouls || $.ps || $.saturation)
            {
                result.push($);
                console.log(result); // print the actual state of result
//              console.log(i); prints 0 then 1 then ...
                i++;
            }

        });
        console.log(i); // prints 0
    });
    console.log(result); // prints []
    return result;
}

let result = create_indicators();
 console.log(result); // prints []

它显示:

[]

为什么readFile中的回调函数有它自己的变量?导致它异步?但是当我使用readFileSync时它也不起作用。

如何让结果得到我投入的所有值?当我在result.push($)之后控制日志结果时;它的工作原理使我不是我的解析器,每次我也正确缩进。

3 个答案:

答案 0 :(得分:0)

这是你的问题:

   fs.readFileSync('../data/7XXX7/files/' + file, 'utf8', function (err, data) {

readFileSync不会将回调作为参数。它返回数据或引发异常。它是同步的(正如名称中的“同步”所示)并且您正在使用它,就好像它是异步的一样。

参见文档:

答案 1 :(得分:0)

  1. readFileSync 没有回调。它是同步的。
  2. 使用 fs.readdir 获取您要阅读的文件列表。请参阅How do you get a list of the names of all files present in a directory in Node.js?
  3. 需要了解回调的工作原理。
  4. readFileSync 没有回调。解释回调如何在异步 fs.readFile fs.readdir

    中工作可能会有所帮助

    当您进行异步操作时,因为您不知道它何时完成,您将在参数中传入一个函数(回调),并在操作结束时运行它。

    fs.readFile('/etc/passwd', function (err, data) {
      if (err) throw err;
      console.log(data);
    });
    
    上面代码中的

    fs.readFile 将在完成执行时运行函数(错误,数据),并将数据作为第二个参数传入。如果发生错误,它将作为第一个参数传递错误。

    您还可以获得一个回调函数,定义解析结束时要执行的操作。回调将需要采取错误和结果。 (如果您需要错误)

    读: http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/

    所以你的create_indicators函数应该采用回调函数。

    fs = require("fs")
    function create_indicators(folderPath, callback) {
        let result = [];
        fs.readdir(folderPath, (err, files) => {
            if (err)
                callback(err, null); //pass the error to callback if there is any
            else {
    
                files.forEach((file, index, filesArray) => {
                    fs.readFile(file, (err, data) => {
                        if (err)
                            callback(err, null); //pass the error to callback if there is any
                        else {
    
                            //.....parse....
                            result.push(data);
    
                            // pass data to callback function when it is the last result
                            if (result.length == filesArray.length)
                                callback(null, result);
    
                        }
                    });
                });
    
            }
        })
    }
    

    当你调用它时,传递你想要做的结果和错误作为一个函数。

       create_indicators(".", function(err,result){
        if (err)
          console.error("Got error:", err);
        else
          console.log("Got result:", result);
          //do what you want with the final result
        })
    

    一旦你完成了回调工作,请查看Promise,这将使此过程更简洁。阅读:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

答案 2 :(得分:0)

您的代码不会等待文件被读取,并且在继续之前将结果推送到result。如果你对数组中的项进行异步操作,我建议使用promises并使用Promise.all()等待每个文件在尝试使用结果之前进行读取和处理。你可以这样做:

function create_indicators() {
    const result = fs.readdirSync('../data/7XXX7/files/').map(file => 
        new Promise((resolve, reject) => {
            fs.readFile('../data/7XXX7/files/' + file, 'utf8', (err, data) => {
                if (err) reject(err);
                // do whatever
                if ($.poids || /* ... */ $.saturation) {
                    // ...
                    resolve($); // instead of `result.push($);`
                } else {
                    resolve(); // can't reject for `Promise.all()` to work
                }
            })
        }));
    return Promise.all(result).then(items => items.filter(item => item));
}

create_indicators().then(indicators => {
    // do something with your list of indicators
}).catch(err => {
    // handle error
});

它为目录中的每个文件创建一个承诺,该承诺在处理文件时解析。如果您的条件不满足,则根据项目解决,如果有错误则拒绝(承诺相当于throw)。由于您只需要符合条件的项目,因此您可以对Promise.all()的结果进行过滤以除去数组中的任何undefined(您也可以删除条件检查fs.readFile回调,如果您愿意,请在过滤器中执行此操作。这将返回一个使用已过滤列表解析的承诺。