Sprawdź synchronicznie, czy plik / katalog istnieje w Node.js

1207

Jak mogę synchronicznie sprawdzić za pomocą node.js , czy plik lub katalog istnieje?

Ragnis
źródło
57
Operacje synchroniczne doskonale nadają się do wykonywania jednorazowych operacji na plikach / katalogach przed zwróceniem modułu. Na przykład ładowanie pliku konfiguracyjnego.
żartuje
1
@PaulDraper z ciepłą pamięcią podręczną nie jest prawdą we wszystkich przypadkach.
mikemaccana,
11
Niezależnie od wydajności, czasami chcesz po prostu uruchomić ją w sposób zsynchronizowany, aby uzyskać doświadczenie programisty. Na przykład, jeśli używasz Węzła do skryptu przetwarzania danych, który z założenia powinien blokować, w takim przypadku asynchronia existspo prostu dodaje niepotrzebne wywołania zwrotne.
Kunok,
2
Zdecydowanie +1 do oświadczenia Kunoka. W pozostałej części kodu komplikuję kod tylko wtedy, gdy jest to wąskie gardło, w którym szybkość ma znaczenie. Dlaczego nie miałbym zastosować tej zasady do odczytu plików? W wielu częściach wielu programów prostota / czytelność kodu może być ważniejsza niż szybkość wykonywania. Jeśli jest to wąskie gardło, użyję metod asynchronicznych, aby nie dopuścić do zatrzymania dalszego wykonywania kodu. W przeciwnym razie ... synchronizacja jest świetna. Nie ślepo nienawidzę synchronizacji.
BryanGrezeszak
3
Proszę ... nie „warte odnotowania”, ponieważ użytkownik wyraźnie pyta, jak to zrobić synchronicznie.
jClark,

Odpowiedzi:

2238

Odpowiedź na to pytanie zmieniała się na przestrzeni lat. prąd Odpowiedź jest tutaj na górze, a następnie przez różne odpowiedzi przez lata w porządku chronologicznym:

Aktualna odpowiedź

Możesz użyć fs.existsSync():

const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
    // Do something
}

Był przestarzały przez kilka lat, ale już nie jest. Z dokumentów:

Pamiętaj, że fs.exists()jest przestarzałe, ale fs.existsSync()nie jest. (Parametr wywołania zwrotnego fs.exists()akceptuje parametry niezgodne z innymi wywołaniami zwrotnymi Node.js. fs.existsSync()Nie używa wywołania zwrotnego.)

W szczególności poprosiłeś o sprawdzenie synchroniczne , ale jeśli zamiast tego możesz użyć sprawdzenia asynchronicznego (zwykle najlepiej z I / O), użyj, fs.promises.accessjeśli używasz asyncfunkcji lub fs.access(ponieważ existsjest przestarzałe ), jeśli nie:

W asyncfunkcji:

try {
    await fs.promises.access("somefile");
    // The check succeeded
} catch (error) {
    // The check failed
}

Lub z oddzwanianiem:

fs.access("somefile", error => {
    if (!error) {
        // The check succeeded
    } else {
        // The check failed
    }
});

Odpowiedzi historyczne

Oto odpowiedzi historyczne w kolejności chronologicznej:

  • Oryginalna odpowiedź z 2010 roku
    ( stat/ statSynclub lstat/ lstatSync)
  • Aktualizacja z września 2012 r.
    ( exists/ existsSync)
  • Aktualizacja z lutego 2015 r.
    (Zwracając uwagę na zbliżające się wycofanie exists/ existsSync, więc prawdopodobnie wróciliśmy do stat/ statSynclub lstat/ lstatSync)
  • Zaktualizuj grudzień 2015 r.
    (Jest też fs.access(path, fs.F_OK, function(){})/ fs.accessSync(path, fs.F_OK), ale zwróć uwagę, że jeśli plik / katalog nie istnieje, jest to błąd; fs.statzaleca się korzystanie z dokumentów, fs.accessjeśli chcesz sprawdzić istnienie bez otwierania)
  • Aktualizacja z grudnia 2016 r.
    fs.exists() Jest nadal przestarzała, ale fs.existsSync()nie jest już przestarzała. Możesz teraz bezpiecznie z niego korzystać.

Oryginalna odpowiedź z 2010 roku:

Możesz użyć statSynclub lstatSync( link do dokumentu ), który daje ci fs.Statsobiekt . Zasadniczo, jeśli dostępna jest synchroniczna wersja funkcji, będzie miała taką samą nazwę jak wersja asynchroniczna Syncna końcu. Podobnie statSyncjest z synchroniczną wersją stat; lstatSyncjest wersją synchroniczną lstatitp.

lstatSync mówi zarówno, czy coś istnieje, a jeśli tak, to czy jest to plik, czy katalog (lub w niektórych systemach plików, dowiązanie symboliczne, urządzenie blokowe, urządzenie znakowe itp.), np. czy musisz wiedzieć, czy istnieje i czy jest katalog:

var fs = require('fs');
try {
    // Query the entry
    stats = fs.lstatSync('/the/path');

    // Is it a directory?
    if (stats.isDirectory()) {
        // Yes it is
    }
}
catch (e) {
    // ...
}

... i podobnie, jeśli jest to plik, istnieje isFile; jeśli jest to urządzenie blokowe, istnieje isBlockDeviceitp. itd. Uwaga try/catch; zgłasza błąd, jeśli pozycja w ogóle nie istnieje.

Jeśli nie obchodzi Cię, czym jest wpis i chcesz tylko wiedzieć, czy istnieje, możesz użyć path.existsSync(lub najnowszej wersji fs.existsSync), jak zauważył użytkownik 618408 :

var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
    // ...
}

Nie wymaga, try/catchale nie daje żadnych informacji o tym, co to jest, po prostu to, że tam jest. path.existsSynczostał wycofany dawno temu.


Uwaga dodatkowa: wyraźnie zapytałeś, jak sprawdzać synchronicznie , więc użyłem xyzSyncpowyższych wersji funkcji. Ale tam, gdzie to możliwe, we / wy naprawdę najlepiej unikać połączeń synchronicznych. Wywołania do podsystemu we / wy zajmują dużo czasu z punktu widzenia procesora. Zwróć uwagę, jak łatwo jest zadzwonić, lstata nie lstatSync:

// Is it a directory?
lstat('/the/path', function(err, stats) {
    if (!err && stats.isDirectory()) {
        // Yes it is
    }
});

Ale jeśli potrzebujesz wersji synchronicznej, jest ona dostępna.

Aktualizacja z września 2012 r

Poniższa odpowiedź sprzed kilku lat jest teraz trochę nieaktualna. Obecny sposób polega na fs.existsSyncprzeprowadzeniu synchronicznego sprawdzania istnienia pliku / katalogu (lub oczywiście fs.existsna sprawdzeniu asynchronicznym) zamiast napath poniższych wersjach.

Przykład:

var fs = require('fs');

if (fs.existsSync(path)) {
    // Do something
}

// Or

fs.exists(path, function(exists) {
    if (exists) {
        // Do something
    }
});

Aktualizacja z lutego 2015 r

I oto jesteśmy w 2015 roku, a dokumenty Node mówią teraz fs.existsSync(ifs.exists ) „będą przestarzałe”. (Ponieważ ludzie z Węzła uważają, że głupio jest sprawdzać, czy coś istnieje przed otwarciem, co to jest; ale to nie jedyny powód, aby sprawdzić, czy coś istnieje!)

Więc prawdopodobnie wróciliśmy do różnych statmetod ... Aż / chyba, że ​​to się zmieni jeszcze raz, oczywiście.

Aktualizacja grudzień 2015 r

Nie wiem, jak długo tam był, ale jest też fs.access(path, fs.F_OK, ...)/fs.accessSync(path, fs.F_OK) . Przynajmniej w październiku 2016 r. fs.statDokumentacja zaleca używanie fs.accessdo sprawdzania istnienia ( zalecane jest „sprawdzenie, czy plik istnieje bez manipulowania nim później fs.access() ). Pamiętaj jednak, że brak dostępu jest uważany za błąd , więc prawdopodobnie byłoby to najlepsze, jeśli spodziewasz się, że plik będzie dostępny:

var fs = require('fs');

try {
    fs.accessSync(path, fs.F_OK);
    // Do something
} catch (e) {
    // It isn't accessible
}

// Or

fs.access(path, fs.F_OK, function(err) {
    if (!err) {
        // Do something
    } else {
        // It isn't accessible
    }
});

Aktualizacja z grudnia 2016 r

Możesz użyć fs.existsSync():

if (fs.existsSync(path)) {
    // Do something
}

Był przestarzały przez kilka lat, ale już nie jest. Z dokumentów:

Pamiętaj, że fs.exists()jest przestarzałe, ale fs.existsSync()nie jest. (Parametr wywołania zwrotnego fs.exists()akceptuje parametry niezgodne z innymi wywołaniami zwrotnymi Node.js. fs.existsSync()Nie używa wywołania zwrotnego.)

TJ Crowder
źródło
7
path.exists i path.existsSync zostały wycofane na korzyść fs.exists i fs.existsSync
Drew
15
„Ludzie węzłów uważają, że głupio jest sprawdzać, czy coś istnieje przed otwarciem, co to jest;” Dlaczego głupio jest sprawdzać, czy plik istnieje?
Petr Hurtak,
32
@PetrHurtak: Nie zawsze (ponieważ istnieje wiele powodów, aby sprawdzić istnienie), ale jeśli zamierzasz otworzyć plik, najlepiej po prostu openwywołać połączenie i obsłużyć wyjątek lub cokolwiek, jeśli plik nie był znaleziony. W końcu prawdziwy świat jest chaotyczny: jeśli najpierw sprawdzisz i już tam jest, to nie znaczy, że będzie tam nadal, gdy spróbujesz go otworzyć; jeśli najpierw sprawdzisz, a go nie ma, to nie znaczy, że nie będzie go ani chwili później. Takie rzeczy w taktach wydają się być przypadkami na krawędzi, ale pojawiają się cały czas . Więc jeśli zamierzasz otworzyć, nie ma sensu sprawdzać najpierw.
TJ Crowder,
13
I tutaj pomyślałem, że używanie anty-wzorca do sterowania przepływem jest anty-wzorzec: link
argyle
4
@jeromeyers: Możesz, ale Ionică już to zrobiła dla Ciebie (patrz komentarz powyżej ). :-)
TJ Crowder
124

Patrząc na źródło, istnieje synchroniczna wersja path.exists- path.existsSync. Wygląda na to, że zgubił się w dokumentacji.

Aktualizacja:

path.existsi path.existsSyncsą teraz przestarzałe . Proszę użyć fs.existsifs.existsSync .

Aktualizacja 2016:

fs.exists i fs.existsSyncrównież zostały wycofane . Zamiast tego użyj fs.stat () lub fs.access () .

Aktualizacja 2019:

użyć fs.existsSync. To nie jest przestarzałe. https://nodejs.org/api/fs.html#fs_fs_existssync_path

Jeff
źródło
1
ścieżka.existsSync (p) znajduje się w dokumentach 0.4.10 nodejs.org/docs/v0.4.10/api/path.html
Paul Beusterien
21
W rzeczywistości nowsza odpowiedź: path.existsSync jest przestarzała. To się teraz nazywa fs.existsSync.
Olivier Lalonde
9
Teraz doktorzy mówią, że f. Istniejące będą przestarzałe. nodejs.org/api/fs.html#fs_fs_existssync_path
Greg Hornby
Napisałem małą bibliotekę, aby zastąpić starą existsfunkcję:is-there
Ionică Bizău,
6
currenct docs (wersja ~ 9) tylko oznaczone fs.existsjako przestarzałe, a fs.existsSyncnie jest!
Kunok,
57

Korzystając z obecnie zalecanych (od 2015 r.) Interfejsów API (według dokumentów węzła), robię to:

var fs = require('fs');

function fileExists(filePath)
{
    try
    {
        return fs.statSync(filePath).isFile();
    }
    catch (err)
    {
        return false;
    }
}

W odpowiedzi na kwestię EPERM podniesioną przez @broadband w komentarzach, porusza to dobry punkt. fileExists () prawdopodobnie nie jest dobrym sposobem na przemyślenie tego w wielu przypadkach, ponieważ fileExists () nie może tak naprawdę obiecać zwrotu logicznego. Możesz być w stanie definitywnie ustalić, że plik istnieje lub nie istnieje, ale możesz również otrzymać błąd uprawnień. Błąd uprawnień niekoniecznie oznacza, że ​​plik istnieje, ponieważ może brakować uprawnień do katalogu zawierającego plik, który sprawdzasz. I oczywiście istnieje szansa, że ​​napotkasz inny błąd w sprawdzaniu istnienia pliku.

Tak więc mój powyższy kod to tak naprawdę robiFileExistAndDoIHaveAccessToIt (), ale twoim pytaniem może być doesFileNotExistAndCouldICreateIt (), co byłoby zupełnie inną logiką (która musiałaby uwzględniać między innymi błąd EPERM).

Podczas gdy odpowiedź fs.existsSync odnosi się bezpośrednio do pytania zadanego tutaj, często nie jest to, czego chcesz (nie chcesz tylko wiedzieć, czy „coś” istnieje na ścieżce, prawdopodobnie zależy ci na tym, czy „rzecz” istnieje plik lub katalog).

Najważniejsze jest to, że jeśli sprawdzasz, czy plik istnieje, prawdopodobnie robisz to, ponieważ zamierzasz podjąć pewne działania w oparciu o wynik, a ta logika (sprawdzenie i / lub kolejne działanie) powinna uwzględniać pomysł że rzecz znaleziona w tej ścieżce może być plikiem lub katalogiem i że podczas sprawdzania możesz napotkać EPERM lub inne błędy.

BobDickinson
źródło
4
Fajnie, dodałem || isDirectory (), aby uczynić z niego narzędzie do sprawdzania plików / folderów. var stats = fs.statSync (filePath); zwraca stats.isFile () || stats.isDirectory ();
Bob
4
Jeśli program nie ma praw dostępu do pliku, nadal zwraca wartość false, mimo że plik istnieje, tzn. Usuwa wszystkie platformy z pliku chmod ugo-rwx file.txt lub w systemie Windows Kliknij prawym przyciskiem myszy ... Komunikat o wyjątku: wyjątek fs.statSync (./ f.txt): Błąd: EPERM: operacja niedozwolona, ​​stat „X: \ f.txt”. Więc ten przypadek nie jest objęty górnym kodem.
Internet szerokopasmowy
2
Wow, JS jest czasem opóźniony. Więc na pewno w 97% użyjesz tego pliku, ale nie masz prostego wykorzystania file.exists()dla 3% i zamiast tego zmuszasz nas do zawinięcia tego w try catch? Zyskaj prawdziwy ... Dziwka dnia.
wydalony
20

Kolejna aktualizacja

Konieczności odpowiedzi na to pytanie sobie, spojrzał w górę docs węzła zdaje należy nie używać fs.exists, zamiast używać fs.open i używać outputted błąd wykryć, jeśli plik nie istnieje:

z dokumentów:

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 fs.exists () i fs.open (). Wystarczy otworzyć plik i obsłużyć błąd, gdy go nie ma.

http://nodejs.org/api/fs.html#fs_fs_exists_path_callback

Melbourne2991
źródło
1
czy można to zrobić za pomocą openSync, a nie open
Greg Hornby
1
@GregHornby Wyobrażam sobie, że powinien działać tak samo z openSync
Melbourne2991
2
Dla tych, którzy wciąż potrzebują, exists a existsSyncja stworzyłem is-there.
Ionică Bizău
6
Ta deprecjacja mnie wkurza. Otwarcie pliku tylko w celu sprawdzenia, czy wystąpił błąd, wydaje się marnotrawstwem zasobów, gdy potrzebna jest tylko wiedza o istnieniu pliku.
Josh Hansen
11

Używam funkcji poniżej, aby sprawdzić, czy plik istnieje. Łapie także inne wyjątki. Więc w przypadku problemów z prawami np. chmod ugo-rwx filenameLub w Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..funkcji Windows zwraca wyjątek tak jak powinien. Plik istnieje, ale nie mamy prawa dostępu do niego. Błędem byłoby ignorowanie tego rodzaju wyjątków.

function fileExists(path) {

  try  {
    return fs.statSync(path).isFile();
  }
  catch (e) {

    if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
      console.log("File does not exist.");
      return false;
    }

    console.log("Exception fs.statSync (" + path + "): " + e);
    throw e; // something else went wrong, we don't have rights, ...
  }
}

Wyjście wyjątku, dokumentacja błędów nodejs w przypadku, gdy plik nie istnieje:

{
  [Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
  errno: -4058,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'X:\\delsdfsdf.txt'
}

Wyjątek w przypadku, gdy nie mamy uprawnień do pliku, ale istnieje:

{
  [Error: EPERM: operation not permitted, stat 'X:\file.txt']
  errno: -4048,
  code: 'EPERM',
  syscall: 'stat',
  path: 'X:\\file.txt'
}
Internet szerokopasmowy
źródło
2
Naprawdę tak, jest to jedna z niewielu odpowiedzi, która jest aktualna, ponieważ węzeł przestał
używać
Bah, pobiłeś mnie do tego. Mógłbym zaoszczędzić trochę czasu, gdybym to przeczytał.
jgmjgm
5

fs.exists () jest przestarzałe, nie używaj go https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

Możesz zaimplementować podstawową metodę nodejs zastosowaną w tym miejscu: https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86

function statPath(path) {
  try {
    return fs.statSync(path);
  } catch (ex) {}
  return false;
}

to zwróci obiekt statystyki, a kiedy już dostaniesz obiekt statystyki, możesz spróbować

var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
  // do something
}
gsalgadotoledo
źródło
4

Niektóre odpowiedzi tutaj mówią to fs.existsi fs.existsSyncoba są przestarzałe. Według dokumentów nie jest to już prawdą. Tylko fs.existsjest teraz usunięty:

Zauważ, że fs.exists () jest przestarzała, ale fs.existsSync () nie jest. (Parametr wywołania zwrotnego do fs.exists () akceptuje parametry niespójne z innymi wywołaniami zwrotnymi Node.js. Fs.existsSync () nie używa wywołania zwrotnego).

Możesz więc bezpiecznie używać fs.existsSync () do synchronicznego sprawdzania, czy plik istnieje.

jstice4all
źródło
3

pathModuł nie zapewnia synchroniczną wersję path.existswięc trzeba oszukać wokół zfs modułu.

Najszybszą rzeczą, jaką mogę sobie wyobrazić, jest fs.realpathSyncrzucanie błędu, który musisz złapać, więc musisz stworzyć własną funkcję otoki za pomocą try / catch.

Ivo Wetzel
źródło
1

Testy fileSystem (fs) wyzwalają obiekty błędów, które następnie należy zawinąć w instrukcji try / catch. Zaoszczędź trochę wysiłku i skorzystaj z funkcji wprowadzonej w gałęzi 0.4.x.

var path = require('path');

var dirs = ['one', 'two', 'three'];

dirs.map(function(dir) {
  path.exists(dir, function(exists) {
    var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
    console.log(message);
  });
});

źródło
2
Path.exists jest teraz pod fs, więc jest fs.exists (ścieżka, wywołanie zwrotne)
Todd Moses
0

Dokumenty fs.stat()mówią, że należy użyć, fs.access()jeśli nie zamierzasz manipulować plikiem. Nie podało uzasadnienia, może być szybsze lub mniej użyteczne w pamięci?

Używam węzła do automatyzacji liniowej, więc pomyślałem, że dzielę funkcję, której używam do testowania istnienia pliku.

var fs = require("fs");

function exists(path){
    //Remember file access time will slow your program.
    try{
        fs.accessSync(path);
    } catch (err){
        return false;
    }
    return true;
}
Grallen
źródło
0

zaktualizowany asnwer dla tych osób „poprawnie”, wskazując, że nie odpowiada bezpośrednio na pytanie, więcej oferuje alternatywną opcję.

Rozwiązanie synchronizacji:

fs.existsSync('filePath')zobacz także dokumenty tutaj .

Zwraca true, jeśli ścieżka istnieje, w przeciwnym razie false.

Rozwiązanie Async Promise

W kontekście asynchronicznym można po prostu napisać wersję asynchroniczną metodą synchronizacji za pomocą awaitsłowa kluczowego. Możesz po prostu zmienić metodę wywołania zwrotnego asynchronicznego w taką obietnicę:

function fileExists(path){
  return new Promise((resolve, fail) => fs.access(path, fs.constants.F_OK, 
    (err, result) => err ? fail(err) : resolve(result))
  //F_OK checks if file is visible, is default does no need to be specified.

}

async function doSomething() {
  var exists = await fileExists('filePath');
  if(exists){ 
    console.log('file exists');
  }
}

dokumenty dotyczące dostępu ().

Joel Harkes
źródło
1
OP chce rozwiązania synchronicznego
vdegenne,
powinieneś zaktualizować swój kod dofunction asyncFileExists(path) { //F_OK checks if file is visible, is default does no need to be specified. return new Promise(function (res, rej) { fs.access( path, fs.constants.F_OK, function (err) { err ? rej(err) : res(true); }, ); }); }
pery mimon
0

Możliwe, że jeśli chcesz wiedzieć, czy plik istnieje, planujesz go wymagać, jeśli tak jest.

function getFile(path){
    try{
        return require(path);
    }catch(e){
        return false;
    }
}
SwiftNinjaPro
źródło
-1

Oto proste rozwiązanie tego opakowania:

var fs = require('fs')
function getFileRealPath(s){
    try {return fs.realpathSync(s);} catch(e){return false;}
}

Stosowanie:

  • Działa zarówno dla katalogów, jak i plików
  • Jeśli element istnieje, zwraca ścieżkę do pliku lub katalogu
  • Jeśli element nie istnieje, zwraca wartość false

Przykład:

var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
    console.log('file/dir not found: '+pathToCheck);
} else {
    console.log('file/dir exists: '+realPath);
}

Upewnij się, że używasz operatora ===, aby sprawdzić, czy return jest równe false. Nie ma żadnego logicznego powodu, aby fs.realpathSync () zwrócił false w odpowiednich warunkach pracy, więc myślę, że powinno to działać w 100%.

Wolałbym zobaczyć rozwiązanie, które nie generuje błędu i wynikowego spadku wydajności. Z perspektywy API fs.exists () wydaje się być najbardziej eleganckim rozwiązaniem.

Timothy C. Quinn
źródło
1
@Dan, dzięki. Usunąłem obcięty tekst. Nie pamiętam, co to była notatka. Jeśli mi przyjdzie, dodam notatki.
Timothy C. Quinn
1
Np. Usuwam mój komentarz.
Dan Dascalescu,
-2

Z odpowiedzi wynika, że ​​nie ma w tym celu oficjalnego wsparcia API (jak w przypadku bezpośredniej i wyraźnej kontroli). Wiele odpowiedzi mówi, że używa statystyki, jednak nie są one ścisłe. Nie możemy na przykład założyć, że jakikolwiek błąd zgłoszony przez stat oznacza, że ​​coś nie istnieje.

Powiedzmy, że próbujemy z czymś, co nie istnieje:

$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }

Spróbujmy z czymś, co istnieje, ale nie mamy dostępu do:

$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }

Przynajmniej będziesz chciał:

let dir_exists = async path => {
    let stat;
    try {
       stat = await (new Promise(
           (resolve, reject) => require('fs').stat(path,
               (err, result) => err ? reject(err) : resolve(result))
       ));
    }
    catch(e) {
        if(e.code === 'ENOENT') return false;
        throw e;
    }

    if(!stat.isDirectory())
        throw new Error('Not a directory.');

    return true;
};

Pytanie nie jest jasne, czy rzeczywiście chcesz, aby było synchroniczne, czy też chcesz, aby było napisane tak, jakby było synchroniczne. W tym przykładzie użyto funkcji Oczekiwanie / Async, dzięki czemu jest zapisywane tylko synchronicznie, ale działa asynchronicznie.

Oznacza to, że musisz tak to nazwać na najwyższym poziomie:

(async () => {
    try {
        console.log(await dir_exists('god'));
        console.log(await dir_exists('fsm/appendage'));
    }
    catch(e) {
        console.log(e);
    }
})();

Alternatywą jest użycie .then i .catch na obietnicy zwróconej z wywołania asynchronicznego, jeśli jest ona potrzebna dalej.

Jeśli chcesz sprawdzić, czy coś istnieje, dobrą praktyką jest również upewnienie się, że jest to właściwy typ rzeczy, np. Katalog lub plik. Jest to uwzględnione w przykładzie. Jeśli nie jest to dowiązanie symboliczne, musisz użyć lstat zamiast stat, ponieważ stat automatycznie przejdzie przez linki.

Możesz zastąpić cały asynchroniczny kod, aby zsynchronizować kod tutaj i zamiast tego użyć statSync. Spodziewaj się jednak, że gdy asynchronizacja i oczekiwanie staną się uniwersalne, połączenia synchronizacji staną się w końcu zbędne, aby zostać zdeprecjonowane (w przeciwnym razie będziesz musiał zdefiniować je wszędzie i wyżej, tak jak w przypadku asynchronizacji, co czyni je naprawdę bezcelowymi).

jgmjgm
źródło
1
Pierwotne pytanie tego nie precyzuje. Pokazuję też, jak robić rzeczy jednoznacznie. Wiele odpowiedzi może powodować błędy z powodu niejasności. Ludzie często chcą programować rzeczy tak, aby wyglądały synchronicznie, ale niekoniecznie chcą synchronicznego wykonywania. statSync to nie to samo co kod, który pokazałem. Oba opisy tego, co jest rzeczywiście pożądane, są niejednoznaczne, więc narzucasz tylko swoje osobiste interpretacje. Jeśli znajdziesz odpowiedź, której nie rozumiesz, lepiej po prostu zapytać w komentarzach lub PM, aby dowiedzieć się, jakie zmiany są potrzebne.
jgmjgm
1
Jeśli chcesz, możesz również ukraść mój przykładowy kod, nazwij go odpowiednio, umieść na github, dodaj go do npm, a wtedy odpowiedź będzie tylko jedna linia / link: D.
jgmjgm
Kod jest krótki dla przykładu, ale możesz przesłać sugestię edycji, aby dołączyć &&! IsFile lub sprawdzić linki symboliczne itp. (Ponownie, chociaż pytanie nigdy nie mówi wprost, że tego właśnie chcą). Jak już wskazałem, moja odpowiedź spełnia jedną interpretację pytania i nie robi tego samego, co propozycja jednoliniowa.
jgmjgm