Come acquisire nessun file per fs.readFileSync ()?


135

All'interno di node.js readFile () mostra come acquisire un errore, tuttavia non ci sono commenti per la funzione readFileSync () per quanto riguarda la gestione degli errori. Pertanto, se provo a utilizzare readFileSync () quando non è presente alcun file, viene visualizzato l'errore Error: ENOENT, no such file or directory.

Come posso catturare l'eccezione generata? Il doco non indica quali eccezioni vengono generate, quindi non so quali eccezioni devo catturare. Dovrei notare che non mi piace lo stile generico di 'catch ogni singola possibile eccezione' delle istruzioni try / catch. In questo caso, desidero cogliere l'eccezione specifica che si verifica quando il file non esiste e cerco di eseguire readFileSync.

Nota che sto eseguendo le funzioni di sincronizzazione solo all'avvio prima di servire i tentativi di connessione, quindi non sono richiesti commenti che non dovrei usare le funzioni di sincronizzazione :-)


1
Puoi anche usare fs.existsSync()come puoi vedere nella mia nuova risposta
Francisco Presencia,

Risposte:


206

Fondamentalmente, fs.readFileSyncgenera un errore quando non viene trovato un file. Questo errore proviene dal Errorprototipo e generato usando throw, quindi l'unico modo per catturare è con un try / catchblocco:

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
}

Sfortunatamente non puoi rilevare quale errore è stato generato solo guardando la sua catena di prototipi:

if (err instanceof Error)

è il massimo che puoi fare e questo sarà vero per la maggior parte (se non tutti) degli errori. Quindi suggerirei di andare con la codeproprietà e verificarne il valore:

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

In questo modo, gestisci solo questo errore specifico e butti di nuovo tutti gli altri errori.

In alternativa, puoi anche accedere alla messageproprietà dell'errore per verificare il messaggio di errore dettagliato, che in questo caso è:

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

Spero che questo ti aiuti.


1
Grazie, questa è l'informazione che stavo cercando. Ho appena presunto che sarebbe un tipo specifico di errore. Mi sono anche reso conto di aver frainteso il funzionamento di try / catch, pensavo che si potesse rilevare un tipo di errore specifico (a la java). Grazie per le informazioni Golo. :-)
Metalskin il

2
Anche EACCESil codice deve essere controllato nel if per il caso in cui il file è lì, ma non può essere letto a causa della mancanza dei permessi
Gergely Toth

21

Preferisco questo modo di gestirlo. Puoi verificare se il file esiste in modo sincrono:

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(file, 'utf-8');
}

Nota: se il programma elimina anche i file, questo ha una condizione di competizione come indicato nei commenti. Se tuttavia scrivi o sovrascrivi solo i file, senza eliminarli, allora va benissimo.


2
ora fs.existsSync non è più deprecato : "Nota che fs.exists () è deprecato, ma fs.existsSync () non lo è."
falkodev,

17
Per niente migliore. Cosa succede se il file viene rimosso dal disco tra la chiamata existSync e readFileSync? Il tuo codice ora ha una condizione di gara integrata nell'attesa che accada ...
tkarls

2
@tkarls sì, è assolutamente vero, è stato scritto nel 2015 quando stavo ancora imparando Node.js e ha una condizione di gara. Tuttavia, due cose da notare: la somiglianza di questa condizione di razza è così minima che può essere praticamente ignorata, e la seconda e sostituendo la prima è che oggi userei try / catch con async / wait per rendere il mio codice più flessibile "altre" eccezioni (poiché Node è favorevole alle eccezioni).
Francisco Presencia,

1
Le condizioni di gara non contano fino a quando non lo fanno. Risposte come questa sono perché il software è così pieno di bug, perché è necessario riavviare il computer così spesso, perché ci sono così tante vulnerabilità di sicurezza, ecc. Ecc. Stack Overflow dovrebbe avere un flag per risposte potenzialmente dannose.
Jonathan Tran,

Un altro commento N anni dopo, dopo averne appreso un po 'di più (aggiunta una nota nella risposta). Questo va benissimo nel contesto di un programma per filesystem di sola scrittura, ma come notato se anche i file possono essere rimossi, questo ha una condizione di competizione e non è un codice che scriverei oggi (specialmente a causa di quella sincronizzazione!). Ho anche creato il pacchetto filescon tutto ciò che ho imparato a rendere asincrono e provare / catturare più facilmente.
Francisco Presencia,

11

Devi catturare l'errore e quindi controllare che tipo di errore è.

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
}

... fa 'buttare err;'
drudru,

Esiste un modo per rilevare lo stesso errore con la versione non sincronizzata della funzione?
Ki Jéy,

1
Il codice asincrono di KiJéy passa l'errore come primo argomento del callback, quindi se controlli che otterrai lo stesso comportamento.
loganfsmyth

4

Uso un lambda immediatamente invocato per questi scenari:

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

async versione:

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

Puoi aggiungere al tuo post che la tua soluzione è per ECMAScript 6. A partire dal 01/01/18 non esiste supporto da parte di IE con una copertura di circa il 77% dell'utilizzo del browser ( caniuse.com/#feat=arrow-functions ). Sono curioso, come soddisfare gli utenti di IE?
Metalskin

2
@Metalskin Webpack + Babel. Tuttavia, fsè un modulo Node
sdgfsdh

Ah, non sono in contatto con il nodo, sospetto che il nodo non supportasse ES6 quando ho posto la domanda (potrebbe essere sbagliato). Ho anche dimenticato che questa era una domanda sul nodo ;-)
Metalskin il

l'aggiornamento di questo ... fs.readFileAsync()è ora fs.readFile() e anche non dovrebbe mettere la funzione asincrona all'interno di un try / catch in node.js. il try / catch non otterrà mai l'errore poiché è asincrono. invece passa l'errore nel callback e gestiscilo lì: fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); da: nodejs.org/dist/latest-v12.x/docs/api/…
KH B

Credo che il catch-catch verrà chiamato se la promessa viene rifiutata e tu stai aspettando la promessa.
sdgfsdh,

0

Prova invece ad usare Async per evitare di bloccare l'unico thread che hai con NodeJS. Controlla questo esempio:

const util = require('util');
const fs = require('fs');
const path = require('path');
const readFileAsync = util.promisify(fs.readFile);

const readContentFile = async (filePath) => {
  // Eureka, you are using good code practices here!
  const content = await readFileAsync(path.join(__dirname, filePath), {
    encoding: 'utf8'
  })
  return content;
}

Successivamente è possibile utilizzare questa funzione asincrona con try / catch da qualsiasi altra funzione:

const anyOtherFun = async () => {
  try {
    const fileContent = await readContentFile('my-file.txt');
  } catch (err) {
    // Here you get the error when the file was not found,
    // but you also get any other error
  }
}

Buona programmazione!


0

Il meccanismo JavaScript try ... catch non può essere utilizzato per intercettare errori generati da API asincrone. Un errore comune per i principianti è quello di provare a usare il lancio all'interno di un callback primo errore:

// THIS WILL NOT WORK:
const fs = require('fs');

try {
  fs.readFile('/some/file/that/does-not-exist', (err, data) => {
    // Mistaken assumption: throwing here...
    if (err) {
      throw err;
    }
  });
} catch (err) {
  // This will not catch the throw!
  console.error(err);
}

Questo non funzionerà perché la funzione di callback passata a fs.readFile () viene chiamata in modo asincrono. Quando il callback è stato chiamato, il codice circostante, incluso il blocco try ... catch, sarà già uscito. Generare un errore all'interno del callback può causare l'arresto anomalo del processo Node.js nella maggior parte dei casi. Se i domini sono abilitati o un gestore è stato registrato con process.on ('uncaughtException'), tali errori possono essere intercettati.

riferimento: https://nodejs.org/api/errors.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.