Jeśli wykonujesz tę operację przy uruchamianiu lub inicjowaniu aplikacji, możesz zablokować wykonywanie, ponieważ zrobiłbyś to samo, gdybyś zrobił to asynchronicznie. Jeśli tworzysz katalog jako operację cykliczną, to jego zła praktyka, ale prawdopodobnie nie spowoduje żadnych problemów z wydajnością, ale mimo wszystko jest to zły nawyk. Używaj tylko do uruchamiania aplikacji lub innych jednorazowych operacji.
fs.exists()jest anachronizmem i istnieje tylko z powodów historycznych. Prawie nigdy nie powinno być powodu, aby używać go we własnym kodzie.
W szczególności sprawdzenie, czy plik istnieje przed otwarciem, jest anty-wzorcem, który naraża cię na warunki wyścigu: inny proces może usunąć plik między wywołaniami do fs.exists()i fs.open(). Wystarczy otworzyć plik i obsłużyć błąd, gdy go nie ma.
Ponieważ mówimy raczej o katalogu niż pliku, ta rada sugeruje, że powinieneś bezwarunkowo zadzwonić mkdiri zignorować EEXIST.
Ogólnie powinieneś unikać * Syncmetod. Blokują, co oznacza, że absolutnie nic innego w twoim programie nie może się zdarzyć podczas przechodzenia na dysk. Jest to bardzo kosztowna operacja, a czas potrzebny na złamanie podstawowego założenia pętli zdarzeń węzła.
SyncMetody * są zwykle dobre w szybkich skryptach jednofunkcyjnych (tych, które wykonują jedną rzecz, a następnie wychodzą), ale prawie nigdy nie powinny być używane podczas pisania serwera: serwer nie będzie w stanie odpowiedzieć nikomu przez cały czas trwania żądań We / Wy. Jeśli wiele żądań klientów wymaga operacji we / wy, serwer bardzo szybko się zatrzyma.
Jedynym momentem, w którym rozważę użycie * Syncmetod w aplikacji serwera, jest operacja, która dzieje się raz (i tylko raz) przy uruchomieniu. Na przykład requirefaktycznie używareadFileSync do ładowania modułów.
Nawet wtedy musisz zachować ostrożność, ponieważ wiele synchronicznych operacji we / wy może niepotrzebnie spowalniać czas uruchamiania serwera.
Zamiast tego należy użyć asynchronicznych metod we / wy.
Jeśli więc zbierzemy te porady, otrzymamy coś takiego:
function ensureExists(path, mask, cb){if(typeof mask =='function'){// allow the `mask` parameter to be optional
cb = mask;
mask =0777;}
fs.mkdir(path, mask,function(err){if(err){if(err.code =='EEXIST') cb(null);// ignore the error if the folder already existselse cb(err);// something else went wrong}else cb(null);// successfully created folder});}
I możemy użyć tego w następujący sposób:
ensureExists(__dirname +'/upload',0744,function(err){if(err)// handle folder creation errorelse// we're all good});
Oczywiście nie uwzględnia to przypadków typu edge
Co się stanie, jeśli folder zostanie usunięty podczas działania programu? (zakładając, że sprawdzasz, czy istnieje tylko raz podczas uruchamiania)
Co się stanie, jeśli folder już istnieje, ale ma niewłaściwe uprawnienia?
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple',{ recursive:true},(err)=>{if(err)throw err;});
UWAGA: Musisz zaimportować wbudowany fs Najpierw moduł.
Oto trochę bardziej solidny przykład, który wykorzystuje natywne moduły ES (z włączoną flagą i rozszerzeniem .mjs), obsługuje ścieżki inne niż root i uwzględnia pełne nazwy ścieżek:
import fs from'fs';import path from'path';
createDirectories(pathname){const __dirname = path.resolve();
pathname = pathname.replace(/^\.*\/|\/?[^\/]+\.[a-z]+|\/$/g,'');// Remove leading directory markers, and remove ending /file-name.extension
fs.mkdir(path.resolve(__dirname, pathname),{ recursive:true}, e =>{if(e){
console.error(e);}else{
console.log('Success');}});}
Możesz go używać jak createDirectories('/components/widget/widget.js');.
I oczywiście, prawdopodobnie chciałbyś zyskać więcej fantazji, używając obietnic z asynchronizacją / czekaj, aby wykorzystać tworzenie plików w bardziej czytelny, synchroniczny sposób podczas tworzenia katalogów; ale to wykracza poza zakres pytania.
w przypadku obiecującego podejścia nr 1 możesz ponownie ustawić haczyk. mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
Taka niedoceniana odpowiedź! fs-extra ma dla mnie konieczność. Myślę, że pisanie ponad 10 linii tylko w celu sprawdzenia, czy folder istnieje, jest
aberracją
10
Najlepszym rozwiązaniem byłoby użycie modułu npm o nazwie node-fs-extra . Ma metodę o nazwie, mkdirktóra tworzy wspomniany katalog. Jeśli podasz długą ścieżkę do katalogu, automatycznie utworzy ona foldery nadrzędne. Moduł jest super zestawem modułu npm fs, więc możesz korzystać ze wszystkich funkcji, fstakże po dodaniu tego modułu.
W przypadku Node.js w wersji 7.4.0 dokumentacja stwierdza, że fs.exists()jest przestarzała, ale fs.existsSync()nie jest. Czy możesz dodać link do zasobu informującego, że fs.existsSync()jest amortyzowany?
francis
1
Odpowiedzi zawierające tylko kod nie są zbyt pomocne dla użytkowników, którzy w przyszłości odpowiedzą na to pytanie. Edytuj swoją odpowiedź, aby wyjaśnić, dlaczego kod rozwiązuje pierwotny problem
Dzięki! Wygląda na to, że funkcja istniała w wersji 0.12, przestarzała w wersji 4 i 5 i została przywrócona w wersji 6 i 7 ... Rodzaj funkcji zombi ...
var filessystem = require('fs');var dir ='./path/subpath/';if(!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);}else{
console.log("Directory already exist");}
const fs = require('fs')// in javascriptimport* as fs from"fs"// in typescriptimport fs from"fs"// in typescript// it will create the directory if it does not exist.!fs.existsSync(`./assets/`)&& fs.mkdirSync(`./assets/`,{ recursive:true})
import path from'path';import fs from'fs';(async()=>{const dir = path.join(__dirname,'upload');try{await fs.promises.mkdir(dir);}catch(error){if(error.code ==='EEXIST'){// Something already exists, but is it a file or directory?const lstat =await fs.promises.lstat(dir);if(!lstat.isDirectory()){throw error;}}else{throw error;}}})();
Możesz użyć węzła File System komendy fs.stat, aby sprawdzić, czy katalog istnieje, i fs.mkdir, aby utworzyć katalog z wywołaniem zwrotnym, lub fs.mkdirSync, aby utworzyć katalog bez wywołania zwrotnego, jak w tym przykładzie:
//first require fsconst fs = require('fs');// Create directory if not exist (function)const createDir =(path)=>{// check if dir exist
fs.stat(path,(err, stats)=>{if(stats.isDirectory()){// do nothing}else{// if the given path is not a directory, create a directory
fs.mkdirSync(path);}});};
Oto mała funkcja rekurencyjnego tworzenia katalogów:
const createDir =(dir)=>{// This will create a dir given a path such as './folder/subfolder' const splitPath = dir.split('/');
splitPath.reduce((path, subPath)=>{let currentPath;if(subPath !='.'){
currentPath = path +'/'+ subPath;if(!fs.existsSync(currentPath)){
fs.mkdirSync(currentPath);}}else{
currentPath = subPath;}return currentPath
},'')}
Odpowiedzi:
źródło
Sync
metod jest zwykle nie-nie: nie chcę blokować pętli zdarzeńNie, z wielu powodów.
path
Moduł nie maexists
/existsSync
metody. Jest wfs
module. (Być może właśnie napisałeś literówkę w swoim pytaniu?)Dokumenty wyraźnie zniechęcają do korzystania
exists
.Ponieważ mówimy raczej o katalogu niż pliku, ta rada sugeruje, że powinieneś bezwarunkowo zadzwonić
mkdir
i zignorowaćEEXIST
.Ogólnie powinieneś unikać *
Sync
metod. Blokują, co oznacza, że absolutnie nic innego w twoim programie nie może się zdarzyć podczas przechodzenia na dysk. Jest to bardzo kosztowna operacja, a czas potrzebny na złamanie podstawowego założenia pętli zdarzeń węzła.Sync
Metody * są zwykle dobre w szybkich skryptach jednofunkcyjnych (tych, które wykonują jedną rzecz, a następnie wychodzą), ale prawie nigdy nie powinny być używane podczas pisania serwera: serwer nie będzie w stanie odpowiedzieć nikomu przez cały czas trwania żądań We / Wy. Jeśli wiele żądań klientów wymaga operacji we / wy, serwer bardzo szybko się zatrzyma.Jedynym momentem, w którym rozważę użycie *
Sync
metod w aplikacji serwera, jest operacja, która dzieje się raz (i tylko raz) przy uruchomieniu. Na przykładrequire
faktycznie używareadFileSync
do ładowania modułów.Nawet wtedy musisz zachować ostrożność, ponieważ wiele synchronicznych operacji we / wy może niepotrzebnie spowalniać czas uruchamiania serwera.
Zamiast tego należy użyć asynchronicznych metod we / wy.
Jeśli więc zbierzemy te porady, otrzymamy coś takiego:
I możemy użyć tego w następujący sposób:
Oczywiście nie uwzględnia to przypadków typu edge
źródło
0744 == 484
.Znalazłem i moduł npm, który działa do tego jak urok. Po prostu wykonaj rekursywnie mkdir w razie potrzeby, na przykład „mkdir -p”.
https://www.npmjs.com/package/mkdirp
źródło
mkdir
Metoda ma zdolność do rekursywnie utworzyć żadnych katalogów w ścieżce, które nie istnieją, i ignorować te, które wykonują.Z dokumentów Node v10 / 11 :
UWAGA: Musisz zaimportować wbudowany
fs
Najpierw moduł.Oto trochę bardziej solidny przykład, który wykorzystuje natywne moduły ES (z włączoną flagą i rozszerzeniem .mjs), obsługuje ścieżki inne niż root i uwzględnia pełne nazwy ścieżek:
Możesz go używać jak
createDirectories('/components/widget/widget.js');
.I oczywiście, prawdopodobnie chciałbyś zyskać więcej fantazji, używając obietnic z asynchronizacją / czekaj, aby wykorzystać tworzenie plików w bardziej czytelny, synchroniczny sposób podczas tworzenia katalogów; ale to wykracza poza zakres pytania.
źródło
Na wszelki wypadek zainteresowany wersją jednoliniową. :)
źródło
Możesz po prostu użyć
mkdir
i złapać błąd, jeśli folder istnieje.Jest to asynchroniczne (więc najlepsza praktyka) i bezpieczne.
(Opcjonalnie dodaj drugi argument do trybu).
Inne przemyślenia:
Możesz wtedy użyć lub poczekać, używając natywnego promisify .
Możesz stworzyć własną metodę obietnicy, taką jak (niesprawdzona):
Do sprawdzania synchronicznego możesz użyć:
Możesz też skorzystać z biblioteki, z której dwie są najbardziej popularne
źródło
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==
zamiast!=
Dzięki pakietowi fs-extra możesz to zrobić za pomocą jednej linijki :
źródło
Najlepszym rozwiązaniem byłoby użycie modułu npm o nazwie node-fs-extra . Ma metodę o nazwie,
mkdir
która tworzy wspomniany katalog. Jeśli podasz długą ścieżkę do katalogu, automatycznie utworzy ona foldery nadrzędne. Moduł jest super zestawem modułu npmfs
, więc możesz korzystać ze wszystkich funkcji,fs
także po dodaniu tego modułu.źródło
źródło
fs.exists()
jest przestarzała, alefs.existsSync()
nie jest. Czy możesz dodać link do zasobu informującego, żefs.existsSync()
jest amortyzowany?Apr 2018
: nodejs.org/api/fs.html#fs_fs_existssync_pathTo może ci pomóc :)
źródło
Rozwiązanie
źródło
Chciałbym dodać refaktor Typescript Promise do odpowiedzi josh3736 .
Robi to samo i ma te same przypadki brzegowe, po prostu używa Obietnic, maszynopisów maszynopisowych i działa z „use strict”.
źródło
W przypadku węzła 10 + ES6:
źródło
Możesz użyć węzła File System komendy fs.stat, aby sprawdzić, czy katalog istnieje, i fs.mkdir, aby utworzyć katalog z wywołaniem zwrotnym, lub fs.mkdirSync, aby utworzyć katalog bez wywołania zwrotnego, jak w tym przykładzie:
źródło
Oto mała funkcja rekurencyjnego tworzenia katalogów:
źródło
Za pomocą asynchronizacji / oczekiwania:
Musisz obiecać
fs
:źródło