Bagaimana cara menangkap tidak ada file untuk fs.readFileSync ()?

135

Di dalam node.js readFile () menunjukkan cara menangkap kesalahan, namun tidak ada komentar untuk fungsi readFileSync () terkait penanganan kesalahan. Karena itu, jika saya mencoba menggunakan readFileSync () ketika tidak ada file, saya mendapatkan kesalahan Error: ENOENT, no such file or directory.

Bagaimana cara menangkap pengecualian yang dilemparkan? Doco tidak menyatakan pengecualian apa yang dilemparkan, jadi saya tidak tahu pengecualian apa yang perlu saya tangkap. Saya harus mencatat bahwa saya tidak suka gaya umum coba / tangkap pernyataan try / catch. Dalam hal ini saya ingin menangkap pengecualian spesifik yang terjadi ketika file tidak ada dan saya berusaha melakukan readFileSync.

Harap perhatikan bahwa saya hanya menjalankan fungsi sinkronisasi saat memulai sebelum melakukan upaya koneksi, jadi komentar yang tidak seharusnya saya gunakan fungsi sinkronisasi tidak diperlukan :-)

Kulit logam
sumber
1
Anda juga dapat menggunakan fs.existsSync()sebagaimana dapat dilihat dalam jawaban baru saya
Francisco Presencia

Jawaban:

206

Pada dasarnya, fs.readFileSyncmelempar kesalahan saat file tidak ditemukan. Kesalahan ini berasal dari Errorprototipe dan dibuang menggunakan throw, maka satu-satunya cara untuk menangkapnya adalah dengan sebuah try / catchblok:

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
}

Sayangnya Anda tidak dapat mendeteksi kesalahan yang telah dilemparkan hanya dengan melihat rantai prototipenya:

if (err instanceof Error)

adalah yang terbaik yang dapat Anda lakukan, dan ini akan berlaku untuk sebagian besar (jika tidak semua) kesalahan. Karena itu saya sarankan Anda pergi dengan codeproperti dan memeriksa nilainya:

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

Dengan cara ini, Anda hanya berurusan dengan kesalahan khusus ini dan melemparkan kembali semua kesalahan lainnya.

Atau, Anda juga dapat mengakses messageproperti kesalahan untuk memverifikasi pesan kesalahan rinci, yang dalam hal ini adalah:

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

Semoga ini membantu.

Golo Roden
sumber
1
Terima kasih, itulah info yang saya cari. Saya hanya menduga bahwa itu akan menjadi jenis Kesalahan tertentu. Saya juga baru menyadari bahwa saya salah mengerti bagaimana cara mencoba / menangkap bekerja, saya berpikir bahwa Anda dapat menangkap jenis kesalahan tertentu (ala java). Terima kasih atas info Golo. :-)
Metalskin
2
EACCESKode juga harus diperiksa dalam pernyataan if untuk kasus ketika file ada tetapi tidak dapat dibaca karena kurangnya izin
Gergely Toth
21

Saya lebih suka cara penanganan ini. Anda dapat memeriksa apakah file ada secara sinkron:

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');
}

Catatan: jika program Anda juga menghapus file, ini memiliki kondisi lomba seperti yang tercantum dalam komentar. Namun jika Anda hanya menulis atau menimpa file, tanpa menghapusnya, maka ini sama sekali tidak masalah.

Francisco Presencia
sumber
2
sekarang, fs.existsSync tidak lagi ditinggalkan : "Perhatikan bahwa fs.exists () sudah usang, tetapi fs.existsSync () tidak."
falkodev
17
Sama sekali tidak lebih baik. Bagaimana jika file dihapus dari disk antara panggilan existSync dan readFileSync? Kode Anda sekarang memiliki kondisi balapan yang dibangun untuk menunggu terjadi ...
tkarls
2
@karkar ya itu sepenuhnya benar, yang ditulis pada tahun 2015 ketika saya masih belajar Node.js dan memiliki kondisi balapan. Namun, dua hal yang perlu diperhatikan: kesamaan kondisi lomba ini sangat minim sehingga pada dasarnya dapat diabaikan, dan yang kedua dan di atas yang pertama adalah bahwa saya akan menggunakan try / catch with async / menunggu saat ini membuat kode saya lebih fleksibel untuk pengecualian "lainnya" (karena Node ramah terhadap pengecualian).
Francisco Presencia
1
Kondisi ras tidak masalah sampai mereka melakukannya. Jawaban seperti ini adalah alasan mengapa perangkat lunak begitu penuh bug, mengapa Anda harus sering me-restart komputer, mengapa ada begitu banyak kerentanan keamanan, dll., Dll. Stack Overflow harus memiliki tanda untuk jawaban yang berpotensi berbahaya.
Jonathan Tran
Komentar lain N tahun kemudian, setelah mempelajari banyak lagi (menambahkan catatan dalam jawaban). Ini benar-benar baik dalam konteks program filesystem hanya-menulis, tetapi seperti dicatat jika file juga dapat dihapus ini memiliki kondisi ras dan itu bukan kode saya akan menulis saat ini (terutama karena Sinkronisasi itu!). Saya juga telah membuat paket filesdengan semua yang telah saya pelajari untuk membuat async dan mencoba / menangkap dengan lebih mudah.
Francisco Presencia
11

Anda harus menangkap kesalahan dan kemudian memeriksa jenis kesalahan itu.

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
}
loganfsmyth
sumber
... buat yang 'melempari kesalahan;'
drudru
Apakah ada cara untuk menangkap kesalahan yang sama dengan versi fungsi yang tidak disinkronkan?
Ki Jéy
1
@ KiJéy kode Async meneruskan kesalahan sebagai argumen pertama dari callback, jadi jika Anda memeriksa bahwa Anda akan mendapatkan perilaku yang sama.
loganfsmyth
4

Saya menggunakan lambda yang langsung dipanggil untuk skenario ini:

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

async Versi: kapan:

const config = await (async () => {
  try {
    return JSON.parse(await fs.readFileAsync('config.json'));
  } catch (error) {
    return {};
  }
})();
sdgfsdh
sumber
Anda mungkin ingin menambahkan ke posting Anda bahwa solusi Anda adalah untuk ECMAScript 6. Pada 01/01/18 tidak ada dukungan dari IE dengan sekitar 77% cakupan penggunaan browser ( caniuse.com/#feat=arrow-functions ). Saya ingin tahu, bagaimana Anda melayani pengguna IE?
Metalskin
2
@Metalskin Webpack + Babel. Namun, fsadalah modul Node
sdgfsdh
Ahh, saya tidak terhubung dengan node, saya curiga node tersebut tidak mendukung ES6 ketika saya mengajukan pertanyaan (bisa salah). Agak lupa ini adalah pertanyaan simpul juga ;-)
Metalskin
memperbarui ini ... fs.readFileAsync()sekarang fs.readFile() dan juga tidak boleh meletakkan fungsi async di dalam try / catch di node.js. coba / tangkap tidak akan pernah mendapatkan kesalahan karena async. alih-alih meneruskan kesalahan dalam panggilan balik dan menanganinya di sana: fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); dari: nodejs.org/dist/latest-v12.x/docs/api/…
KH B
Saya percaya bahwa try-catch akan dipanggil jika janji itu ditolak dan Anda sedang menunggu janji itu.
sdgfsdh
0

Coba gunakan Async sebagai gantinya untuk menghindari memblokir satu-satunya utas yang Anda miliki dengan NodeJS. Lihat contoh ini:

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;
}

Nanti dapat menggunakan fungsi async ini dengan mencoba / menangkap dari fungsi lain:

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
  }
}

Selamat Coding!

jdnichollsc
sumber
0

JavaScript try… catch mekanisme tidak dapat digunakan untuk mencegat kesalahan yang dihasilkan oleh asynchronous API. Kesalahan umum untuk pemula adalah mencoba menggunakan lemparan di dalam panggilan balik kesalahan-pertama:

// 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);
}

Ini tidak akan berfungsi karena fungsi panggilan balik yang dilewatkan ke fs.readFile () dipanggil secara tidak sinkron. Pada saat callback dipanggil, kode di sekitarnya, termasuk blok try ... catch, sudah keluar. Melempar kesalahan di dalam callback dapat merusak proses Node.js dalam banyak kasus. Jika domain diaktifkan, atau handler telah terdaftar dengan process.on ('uncaughtException'), kesalahan tersebut dapat dicegat.

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

ViktorKrpn
sumber