Fs.readFileSync () için dosya nasıl yakalanmaz?


135

Node.js içinde readFile () , bir hatanın nasıl yakalanacağını gösterir, ancak hata işlemeye ilişkin readFileSync () işlevi için bir açıklama yoktur . Bu nedenle, dosya yokken readFileSync () kullanmaya çalışırsam, hatayı alıyorum Error: ENOENT, no such file or directory.

Atılan istisnayı nasıl yakalayabilirim? Doco hangi istisnaların atıldığını belirtmez, bu yüzden hangi istisnaları yakalamam gerektiğini bilmiyorum. Try / catch deyimlerinin genel 'olası her istisnayı yakala' stilini sevmediğimi not etmeliyim. Bu durumda, dosya mevcut olmadığında oluşan özel istisnayı yakalamak istiyorum ve readFileSync'i gerçekleştirmeye çalışıyorum.

Lütfen senkronizasyon işlevlerini yalnızca başlangıçta bağlantı girişimlerine hizmet vermeden önce gerçekleştirdiğimi, bu nedenle senkronizasyon işlevlerini kullanmamam gerektiğini belirten yorumların gerekli olmadığını unutmayın :-)


1
Ayrıca kullanabilirsiniz fs.existsSync()şekilde görülebilir benim yeni cevap
Francisco Presencia

Yanıtlar:


206

Temel olarak, fs.readFileSyncbir dosya bulunamadığında bir hata atar. Bu hata Errorprototipten kaynaklanıyor ve kullanılarak atılıyor throw, bu nedenle yakalamanın tek yolu bir try / catchblokla:

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
}

Ne yazık ki sadece prototip zincirine bakarak hangi hatanın atıldığını tespit edemezsiniz:

if (err instanceof Error)

yapabileceğinizin en iyisidir ve bu, çoğu (hepsi değilse de) hata için geçerli olacaktır. Bu nedenle, codemülke gitmenizi ve değerini kontrol etmenizi öneririm :

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

Bu şekilde, yalnızca bu belirli hatayla ilgilenir ve diğer tüm hataları yeniden atarsınız.

Alternatif olarak, messageayrıntılı hata mesajını doğrulamak için hatanın özelliğine de erişebilirsiniz, bu durumda:

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

Bu yardımcı olur umarım.


1
Teşekkürler, aradığım bilgi buydu. Bunun belirli bir Hata türü olacağını varsaydım. Ayrıca dene / yakala işlevinin nasıl çalıştığını yanlış anladığımı da yeni fark ettim, belirli bir hata türünü (a la java) yakalayabileceğinizi düşünüyordum. Golo bilgisi için teşekkürler. :-)
Metalskin

2
Ayrıca EACCES, dosyanın orada olduğu ancak izin eksikliğinden dolayı okunamadığı durumlarda kod if ifadesinde kontrol edilmelidir
Gergely Toth

21

Bunu bu şekilde halletmeyi tercih ederim. Dosyanın eşzamanlı olarak var olup olmadığını kontrol edebilirsiniz:

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

Not: Programınız dosyaları da silerse, bunun yorumlarda belirtildiği gibi bir yarış durumu vardır. Bununla birlikte, dosyaları silmeden yalnızca yazar veya üzerine yazarsanız, bu tamamen iyidir.


2
şimdi, fs.existsSync artık kullanımdan kaldırılmıyor : "fs.exists () 'in kullanımdan kaldırıldığını, ancak fs.existsSync ()' in kullanılmadığını unutmayın."
falkodev

17
Hiç de iyi değil. Dosya, containsSync ve readFileSync çağrısı arasında diskten kaldırılırsa ne olur? Kodunuz artık gerçekleşmeyi bekleyen yerleşik bir yarış durumuna sahip ...
tkarls

2
@tkarls evet, bu tamamen doğru, 2015 yılında hala Node.js öğrenirken yazılmıştı ve bir yarış durumu var. Bununla birlikte, dikkat edilmesi gereken iki nokta: Bu yarış durumunun olasılığı o kadar az ki temelde göz ardı edilebiliyor ve ikincisi ve ilkine süper önem vermek, bugünlerde kodumu daha esnek hale getirmek için zaman uyumsuz / await ile dene / yakala kullanacağım. "diğer" istisnalar (Node istisna dostu olduğundan).
Francisco Presencia

1
Yarış koşulları, onlar yapana kadar önemli değil. Bunun gibi yanıtlar, yazılımın neden bu kadar hatalarla dolu olduğu, neden bilgisayarınızı bu kadar sık ​​yeniden başlatmanız gerektiği, neden bu kadar çok güvenlik açığı olduğu vb. Şeklindedir. Stack Overflow, potansiyel olarak zararlı yanıtlar için bir işarete sahip olmalıdır.
Jonathan Tran

N yıl sonra başka bir yorum, birkaç tane daha öğrendikten sonra (cevaba bir not eklenmiştir). Bu, salt yazılabilir bir dosya sistemi programı bağlamında tamamen iyidir, ancak belirtildiği gibi, dosyalar da kaldırılabilirse, bunun bir yarış koşulu vardır ve bugünlerde yazdığım kod değildir (özellikle bu Senkronizasyon nedeniyle!). Ayrıca files, eşzamansız ve denemek / yakalamak için öğrendiğim her şeyi içeren paketi de yazdım.
Francisco Presencia

11

Hatayı yakalamanız ve sonra ne tür bir hata olduğunu kontrol etmeniz gerekir.

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
}

... bunu 'hata at' yap;
drudru

İşlevin senkronize olmayan sürümüyle aynı hatayı yakalamanın bir yolu var mı?
Ki Jéy

1
@ KiJéy Async kodu, hatayı geri aramanın ilk argümanı olarak iletir, bu nedenle aynı davranışı aldığınızı kontrol ederseniz.
loganfsmyth

4

Bu senaryolar için hemen çağrılan bir lambda kullanıyorum:

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

async versiyon:

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

Gönderinize, çözümünüzün ECMAScript 6 için olduğunu eklemek isteyebilirsiniz. 01/01/18 itibariyle, tarayıcı kullanımının yaklaşık% 77 kapsamı ile IE'den destek yoktur ( caniuse.com/#feat=arrow-functions ). Merak ediyorum, IE kullanıcılarına nasıl hitap ediyorsunuz?
Metalskin

2
@Metalskin Webpack + Babel. Ancak, fsbir Düğüm modülüdür
sdgfsdh

Ahh, düğümle iletişimim yok, soruyu sorduğumda düğümün ES6'yı desteklemediğinden şüpheleniyorum (yanlış olabilir). Bunun bir düğüm sorusu olduğunu da unutmuş gibi ;-)
Metalskin

bunu güncellemek ... fs.readFileAsync()artık fs.readFile() ve eşzamansız işlevi node.js içindeki bir dene / yakala işlevinin içine koymamalı. try / catch, eşzamansız olduğundan hiçbir zaman hatayı almaz. bunun yerine geri aramadaki hatayı iletin ve orada işleyin : fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); from: nodejs.org/dist/latest-v12.x/docs/api/…
KH B

Sözün reddedilmesi ve sözünüzü beklemeniz durumunda, dene-yakala çağrısının yapılacağına inanıyorum.
sdgfsdh

0

NodeJS ile sahip olduğunuz tek iş parçacığını engellemekten kaçınmak için Async kullanmayı deneyin . Bu örneği kontrol edin:

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

Daha sonra bu eşzamansız işlevi başka herhangi bir işlevden dene / yakala ile kullanabilir:

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

Mutlu Kodlama!


0

JavaScript dene… yakalama mekanizması, zaman uyumsuz API'ler tarafından oluşturulan hataları engellemek için kullanılamaz. Yeni başlayanlar için yaygın bir hata, ilk hata geri araması içinde atmayı kullanmaya çalışmaktır:

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

Fs.readFile () öğesine iletilen geri çağrı işlevi eşzamansız olarak çağrıldığından bu işe yaramaz. Geri arama çağrıldığında, try… catch bloğu dahil çevreleyen kod zaten çıkmış olacaktır. Geri çağırmanın içine bir hata atmak çoğu durumda Node.js işlemini çökertebilir. Etki alanları etkinleştirilirse veya bir işleyici process.on ('uncaughtException') ile kaydedilmişse, bu tür hatalar yakalanabilir.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.