NodeJS copyFile然后在回调中取消链接

时间:2018-11-08 13:36:48

标签: node.js fs

我有很多文件(百万)要从一个文件夹复制到另一个文件,但是基于某些解析选项,如果不遵守某些条件,则需要删除该文件。

我正在对文件的本地副本进行解析,因为在网络上解析(读取文件+解析)比在本地进行解析要慢。

我的代码如下:

for (let file of files) {
    fs.copyFile(from, to, err => {
        if (err) return;
        parse(file);
   });
}

parse函数类似于:

parse = file => {
    fs.readFile(file, (err, data) => {
        //do some parsing
        if (notOk) {
            fs.unlink(file);
        };
    }
}

问题在于它正在执行所有copyFile,并且似乎没有用unlink执行回调,而且我真的需要在文件复制完成后立即取消链接,因为我可以没有足够的磁盘空间来首先复制所有文件。

我是否需要使用这些方法的Sync版本?

谢谢

我本来期望这样的输出:

copyFile a
copyFile b
copyFile c
parsing a
copyFile d
unlink a
parsing b
copyFile e
...

但是相反,我拥有所有copyFile并且没有任何解析/取消链接。

2 个答案:

答案 0 :(得分:0)

我认为这正在发生,应对中的回调已完成,因此线程已完成,但是函数无法完成,您可以进行此同步,并且可以正常工作,并且更加清楚,但是其他方法是将功能转换为Promise,以便您可以返回Promise并等待它们。

您可以这样写。

const util = require('util');
const fs = require('fs'); 
const files = ['1.txt', '2.txt', '3.txt', '4.txt'];
//promisify all the fs functions to use.
const copyFilePromise = util.promisify(fs.copyFile); 
const readFilePromise = util.promisify(fs.readFile); 
const unlinkPromise = util.promisify(fs.unlink);

//make a parser function that return a promise.
const parse = (file) => {
    return readFilePromise(file) 
            .then(() => { 
                //do some parsing 
                if(notOk) 
                    return unlinkPromise(file)
    });
};

//store all the promises in an array
let promises = []

//iterate for all the files using the promisify aproach of the functions
for (let file of files){
    //add all the promises to an array of promises.
    promises.push(copyFilePromise(from, to).then(parse(file)).catch(console.error));
}

//wait for all the promises to resolve.
Promise.all(promises);

答案 1 :(得分:0)

如果files包含数百万个文件,则说明您正在开始数百万个并发复制操作,这可能使您的系统不堪重负。

相反,请考虑使用类似async.eachLimit的方式来限制并发复制操作的数量。

未经测试的示例:

const async = require('async');

async.eachLimit(files, 10, (file, callback) => {
  fs.copyFile(from, to, err => {
    if (err) return callback(); // or pass `err`
    parse(file, callback);
  });
});

function parse(file, callback) {
  fs.readFile(file, (err, data) => {
    //do some parsing
    if (notOk) {
      fs.unlink(file, callback);
    } else {
      return callback();
    }
  })
}