Одновременное чтение файлов с помощью nodejs fs

#node.js #fs #readfile #async.js

#node.js #fs #readfile #async.js

Вопрос:

Я хотел знать, какой наиболее эффективный метод одновременного чтения нескольких файлов. у меня есть массив путей к файлам, и я хочу создать массив данных, используя файл чтения fs (не AsyncRead и не используя функцию обратного вызова), упорядоченный в соответствии с индексом массива путей. мне нужно прочитать три файла одновременно, и я не могу найти, как одновременно читать файлы.

Я нашел этот метод, но не могу понять, читает ли он файлы одновременно, и если да, то как:

 ***function simultaneouslyRead(filePath1, filePath2){
    var async = require('async'),
    fs = require('fs'),
    files = [filePath1, filePath2];
    async.map(files, fs.readFile, function(err, files) {
        if(err) {
            throw err;
        }
        files.forEach(function(file) {
          console.log(file.toString());
      });
    });
  }***
 

Ответ №1:

Мы могли бы использовать util.promisify для создания версии fs.ReadFile на основе обещаний, а затем использовать Promise.all для чтения всех файлов в массив, что-то вроде этого:

 const fs = require("fs");
const { promisify } = require("util");

const promiseReadFile = promisify(fs.readFile);

async function readFiles(files) {
    const fileArray = await Promise.all(files.map(file => promiseReadFile(file)));
    console.log("File contents:", fileArray);
    return fileArray;
}

readFiles(['file1.txt', 'file2.txt']);
 

Файловый массив будет содержать массив буферов после считывания данных.

Пересмотренная версия, включающая ошибки из-за любых сбоев чтения:

 const fs = require("fs");

function promiseReadFile(path, options = {}) {
    return new Promise(resolve => { 
        fs.readFile(path, options, (err, data) => resolve({ err, data }));
    });
}

async function readFiles(files) {
    const fileArray = await Promise.all(files.map(file => promiseReadFile(file)));
    console.log("File contents:", fileArray);
    return fileArray;
}

readFiles(['file1.txt', 'file2.txt', 'file3.txt']);
 

Комментарии:

1. Ваши решения в порядке, но если он решит записать обратно file1 и file2, вероятно, не будут точно такими же, верно?

2. Мы считываем каждый файл в буфер в том виде, в каком он находится в данный момент, эффективно делая моментальные снимки содержимого. Конечно, файлы могут измениться до или после. Если бы кто-то хотел заблокировать файлы, можно было бы пойти по этому пути, хотя я считаю, что на данный момент это выходит за рамки вопроса.

3. ваше решение отличное, но что, если в одном файле будет ошибка (не найден, cloudnt открыт и т. Д.), Я хочу, Чтобы конечным результатом было содержимое открытых файлов и ошибки неоткрытых файлов, как перехватить ошибки при чтении одновременно?

4. Это хороший момент. В первой версии, если мы столкнемся с какими-либо ошибками, мы получим отклонение обещания при вызове Promise.all. Мы можем создать пользовательскую функцию promiseReadFile, которая попытается прочитать все файлы и сохранить любые ошибки, возникающие в результате этого. В этом случае мы получим массив результатов: [{data: {}, err: {}, … etc]

Ответ №2:

 const fs= require('fs').promises;

async function readFiles(files) {
    const results = await Promise.allSettled(files.map(file=> fs.readFile(file)));
    console.log(results);
    return results;
}

readFiles(['1.txt', '2.txt', '3.txt']);