为什么此fs.readFile循环未将其结果推送到我的数组? [英] Why is this fs.readFile loop not pushing its results to my array?

查看:58
本文介绍了为什么此fs.readFile循环未将其结果推送到我的数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#!/usr/bin/env node

var fs = require('fs')
  , async = require('async') 
  , program = require('commander')

program
  .version('0.0.1')
  .usage('<keywords>')
  .parse(process.argv)

async.waterfall([
  fs.readdir.bind(fs, __dirname),
  parseHTML,
], saveResult)

function parseHTML(files, callback) {
  var result = []

  files.forEach(function(file) {
    if (file.match(/\.html$/)) {
      fs.readFile(file, 'utf8', function(err, data) {
        if (err) throw err
        result.push(data)
      })
    }
  })

  callback(null, result)
}

function saveResult(err, result) {
  console.log(result)
}

我很困惑,因为console.log(data)确实会输出数据:

I'm confused because console.log(data) does output the data:

<p>File 1</p>

<p>File 2</p>

最后一个result是一个空数组:[]

Yet the final result is an empty array: []

我为什么做错了?

推荐答案

您必须等待查看结果,直到最后一个fs.readFile()操作完成.这些是异步操作,它们将在将来的某个时间完成.您正在检查结果中的任何一个都没有完成.

You have to wait to look at the result until the last fs.readFile() operation has finished. These are async operations and they complete some time in the future. You are examining the result before any of them have finished.

有很多方法可以解决此问题,但是这种方法可能会使您的代码更改最少,因为它只是在统计完成的次数:

There are many ways to approach solving this, but this method would likely cause the least change to your code as it just keeps a counter of how many are done:

function parseHTML(files, callback) {
    var result = [],
        cntr = 0;

    files.forEach(function(file) {
        if (file.match(/\.html$/)) {
            fs.readFile(file, 'utf8', function(err, data) {
                if (err) throw err
                result.push(data)
                    // see if we're done processing all the results
                    ++cntr;
                if (cntr === files.length) {
                    callback(null, result);
                }
            });
        } else {
            ++cntr;
            if (cntr === files.length) {
                callback(null, result);
            }
        }
    });
}


我个人更喜欢使用promise和Promise.all()来解决这个问题.


I'd personally prefer to use promises and Promise.all() to solve this.

以下是使用Bluebird Promise库的版本,该库保留了您的其他一些结构:

Here's a version using the Bluebird promise library that retains some of your other structure:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));

// your other code here

function parseHTML(files, callback) {
    var promises = [];

    files.forEach(function(file) {
        if (file.match(/\.html$/)) {
            promises.push(fs.readFileAsync(file, 'utf8'));
    });
    Promise.all(promises).then(function(results) {
        // all results in results array
        callback(null, results);
    }, function(err) {
       // error here
    });
}


而且,这是一个完全有前途的版本:


And, here's a fully promise version:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));

function parseHTML(files) {
    var promises = [];

    files.forEach(function(file) {
        if (file.match(/\.html$/)) {
            promises.push(fs.readFileAsync(file, 'utf8'));
    });
    return Promise.all(promises);
}

fs.readdirAsync(__dirname).then(parseHTML).then(function(results) {
    // files are in the results array here
}).catch(function(err) {
    // error here
});

这篇关于为什么此fs.readFile循环未将其结果推送到我的数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆