2013-01-18 7 views
82

W węźle node.js readFile() pokazuje, jak uchwycić błąd, jednak nie ma komentarza dla funkcji readFileSync() w zakresie obsługi błędów. Jako takie, jeśli próbuję użyć readFileSync(), gdy nie ma pliku, pojawia się błąd Error: ENOENT, no such file or directory.Jak przechwycić brak pliku dla fs.readFileSync()?

Jak przechwycić zgłaszany wyjątek? Dokument nie określa, jakie wyjątki są zgłaszane, więc nie wiem, jakie wyjątki muszę przechwytywać. Powinienem zauważyć, że nie podoba mi się ogólny styl "catch any single possible except" stylu instrukcji try/catch. W tym przypadku chcę uchwycić wyjątek, który występuje, gdy plik nie istnieje i próbuję wykonać readFileSync.

Należy pamiętać, że jestem pełnienia funkcji synchronizacji tylko na rozruch przed podaniem prób połączeń, więc komentarze, że nie należy używać funkcji synchronizacji nie są wymagane :-)

+0

Można również użyć 'FS. existSync() 'jak można zobaczyć w [moja nowa odpowiedź] (http://stackoverflow.com/a/32804614/938236) –

Odpowiedz

127

Zasadniczo fs.readFileSync zgłasza błąd, gdy plik nie zostanie znaleziony. Ten błąd jest od prototypu Error i wyrzucony za pomocą throw, stąd jedynym sposobem, aby złapać się z try/catch bloku:

var fileContents; 
try { 
    fileContents = fs.readFileSync('foo.bar'); 
} catch (err) { 
    // Here you get the error when the file was not found, 
    // but you also get any other error 
} 

Niestety nie można wykryć który Błąd został wyrzucony po prostu patrząc na jego łańcucha prototypów:

if (err instanceof Error) 

to najlepsze, co możesz zrobić, a dotyczy to większości (jeśli nie wszystkich) błędów. Dlatego sugeruję iść z właściwością code i sprawdzić jego wartość:

if (err.code === 'ENOENT') { 
    console.log('File not found!'); 
} else { 
    throw err; 
} 

W ten sposób mamy do czynienia tylko z tym konkretnym błędu i ponownie rzucić wszystkie inne błędy.

Alternatywnie, można również uzyskać dostęp do Błąd w message obiekt do sprawdzenia szczegółowy komunikat o błędzie, który w tym przypadku wynosi:

ENOENT, no such file or directory 'foo.bar' 

nadzieję, że to pomaga.

+0

Dzięki, oto informacje, których szukałem. Po prostu założyłem, że byłby to specyficzny typ błędu. Zauważyłem też, że źle zrozumiałem, jak działa try/catch, myślałem, że można złapać konkretny typ błędu (a la java). Dzięki za informację Golo. :-) – Metalskin

+0

Nie ma za co :-)! –

+1

Również kod 'EACCES' powinien być zaznaczony w instrukcji if dla przypadku, gdy plik istnieje, ale nie można go odczytać z powodu braku uprawnień –

7

Trzeba złapać błąd i następnie sprawdź, jaki to jest błąd.

try { 
    var data = fs.readFileSync(...) 
} catch (err) { 
    // If the type is not what you want, then just throw the error again. 
    if (err.code !== 'ENOENT') throw err; 

    // Handle a file-not-found error 
} 
+0

... sprawiają, że" throw err; " – drudru

+0

@drudru Dobre połączenie, naprawione. – loganfsmyth

12

Chociaż przyjęte rozwiązanie jest w porządku, znalazłem o wiele lepszy sposób radzenia sobie z tym. można po prostu sprawdzić, czy plik istnieje synchronicznie:

var file = 'info.json'; 
var content = ''; 

// Check that the file exists locally 
if(!fs.existsSync(file)) { 
    console.log("File not found"); 
} 

// The file *does* exist 
else { 
    // Read the file and do anything you want 
    content = fs.readFileSync(this.local, 'utf-8'); 
} 
+2

teraz, fs.existsSync jest już [nie jest przestarzałe] (https://nodejs.org /api/fs.html#fs_fs_existssync_path): "Zauważ, że fs.exists() jest przestarzałe, ale fs.existsSync() nie jest." – falkodev

+3

Nie lepiej. Co się stanie, jeśli plik zostanie usunięty z dysku między wywołaniami existSync i readFileSync? Twój kod ma teraz warunek wyścigowy zbudowany w oczekiwaniu na zdarzenie ... – tkarls

+1

@tkarls Tak, to jest całkowicie poprawne, to zostało napisane w 2015 roku, kiedy wciąż uczyłem się Node.js i ma on stan wyścigu. Należy jednak pamiętać o dwóch rzeczach: podobny stan tego wyścigu jest tak mały, że można go zasadniczo zignorować, a drugim i superseedującym jest to, że używałbym try/catch z async/czekając w dzisiejszych czasach, aby mój kod był bardziej elastyczny "inne" wyjątki (ponieważ węzeł jest przyjazny dla wyjątków). –

3

używam natychmiast powołać lambda dla tych scenariuszy:

const config = (() => { 
    try { 
    return JSON.parse(fs.readFileSync('config.json')); 
    } catch (error) { 
    return {}; 
    } 
})(); 

async wersję:

const config = await (async() => { 
    try { 
    return JSON.parse(await fs.readFileAsync('config.json')); 
    } catch (error) { 
    return {}; 
    } 
})(); 
+0

Możesz dodać do swojego posta, że ​​twoje rozwiązanie jest dla ECMAScript 6. Na 01/01/18 nie ma wsparcia ze strony IE z 77% pokryciem korzystania z przeglądarki (https://caniuse.com/#feat= strzałki-funkcje). Jestem ciekawy, jak sobie radzisz z użytkownikami IE? – Metalskin

+0

@ Web Packetmetalskin + Babel. Jednakże, 'fs' jest modułem węzła – sdgfsdh

+0

Ahh, nie mam kontaktu z węzłem, podejrzewam, że węzeł nie obsługiwał ES6, gdy zadałem pytanie (może być źle). Kinda zapomniała, że ​​to także pytanie o węzeł ;-) – Metalskin