2016-10-27 8 views
6

Załóżmy, że mamy taki program:Czy wiele fs.write do dołączenia do tego samego pliku gwarantuje kolejność wykonywania?

// imagine the string1 to string1000 are very long strings, which will take a while to be written to file system 
var arr = ["string1",...,"string1000"]; 
for (let i = 1; i < 1000; i++) { 
    fs.write("./same/path/file.txt", arr[i], {flag: "a"}}); 
} 

Moje pytanie brzmi, will string1 to string1000 be gurantted to append to the same file in order?

Od fs.write jest funkcja asynchroniczny, nie jestem pewien, jak każde wywołanie fs.write() jest rzeczywiście wykonywana. Zakładam, że wywołanie funkcji dla każdego ciągu powinno być umieszczone gdzieś w another thread (jak callstack?) I po wykonaniu poprzedniego połączenia można wykonać następne połączenie.

Nie jestem pewien, czy moje zrozumienie jest prawidłowe.

Edycja 1

jak w komentarzach i odpowiedziach, widzę fs.write nie jest bezpieczny do wielokrotnego zapisu do tego samego pliku, nie czekając na callback. Ale co z pisanym strumieniem?

Czy użycie następującego kodu zagwarantuje kolejność pisania?

// imagine the string1 to string1000 are very long strings, which will take a while to be written to file system 
var arr = ["string1",...,"string1000"]; 
var fileStream = fs.createWriteFileStream("./same/path/file.txt", { "flags": "a+" }); 
for (let i = 1; i < 1000; i++) { 
    fileStream.write(arr[i]); 
} 
fileStream.on("error",() => {// do something}); 
fileStream.on("finish",() => {// do something}); 
fileStream.end(); 

Wszelkie komentarze i poprawki będą pomocne! Dzięki!

+1

Jeśli masz na myśli [ 'fs.writeFile () '] (https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback), a następnie dokumentacja stwierdza, że ​​_" ... nie jest bezpieczne używanie 'fs.writeFile' wiele razy na tym samym pliku bez oczekiwania na wywołanie zwrotne "_. – robertklep

+0

Należy pamiętać, że ze względu na sposób działania buforowania w pliku node.js, oczekiwanie na oddzwonienie nie ma wpływu na kolejność lub zapisywanie. Niebezpieczna jest możliwość przepełnienia bufora. Tak więc ryzyko nie zawiera zapisów, a nie nieuporządkowanych zapisów. – slebetman

+0

@slebetman, Dzięki za odpowiedź. Ale co naprawdę oznacza tu bufor? – Lubor

Odpowiedz

4

The docs że

Należy pamiętać, że jest to niebezpieczne w użyciu fs.write wielokrotnie na tym samym pliku, nie czekając na oddzwonienie. W tym scenariuszu zdecydowanie zalecana jest fs.createWriteStream.

Korzystanie ze strumienia działa, ponieważ strumienie z natury gwarantują, że kolejność łańcuchów zapisywanych w nich jest tą samą kolejnością, która jest odczytywana z nich.

var stream = fs.createWriteStream("./same/path/file.txt"); 
stream.on('error', console.error); 
arr.forEach((str) => { 
    stream.write(str + '\n'); 
}); 
stream.end(); 

Innym sposobem, aby nadal korzystać fs.write ale również upewnić się rzeczy dzieją się w kolejności jest użycie obietnice utrzymania sekwencyjną logikę.

function writeToFilePromise(str) { 
    return new Promise((resolve, reject) => { 
    fs.write("./same/path/file.txt", str, {flag: "a"}}, (err) => { 
     if (err) return reject(err); 
     resolve(); 
    }); 
    }); 
} 

// for every string, 
// write it to the file, 
// then write the next one once that one is finished and so on 
arr.reduce((chain, str) => { 
    return chain 
    .then(() => writeToFilePromise(str)); 
}, Promise.resolve()); 
+0

, a co z plikiem createWriteFileStream? Jeśli używam filestreamu, czy możemy zagwarantować zamówienie? – Lubor

+0

@Lubor sprawdź moją edycję – nem035

+0

Dzięki! Ale czy mówisz, że stream.write (str) jest operacją synchroniczną? Rozważałem to jako asynchroniczne. – Lubor

0

można synchronizować dostęp do pliku za pomocą odczytu/zapisu blokowania dla węzła, zobacz poniższy przykład można przeczytać documentation

var ReadWriteLock = require('rwlock'); 

var lock = new ReadWriteLock(); 

lock.writeLock(function (release) { 
    fs.appendFile(fileName, addToFile, function(err, data) { 
    if(err) 
     console.log("write error); 
    else  
     console.log("write ok"); 

    release(); // unlock 
    });  
}); 
Powiązane problemy