Làm cách nào để chụp không có tệp cho fs.readFileSync ()?


135

Trong node.js readFile () hiển thị cách ghi lỗi, tuy nhiên không có nhận xét nào cho hàm readFileSync () liên quan đến việc xử lý lỗi. Như vậy, nếu tôi cố gắng sử dụng readFileSync () khi không có tệp, tôi sẽ gặp lỗi Error: ENOENT, no such file or directory.

Làm thế nào để tôi nắm bắt được ngoại lệ bị ném? Tài liệu không nêu rõ ngoại lệ nào được ném, vì vậy tôi không biết ngoại lệ nào tôi cần nắm bắt. Tôi nên lưu ý rằng tôi không thích kiểu câu lệnh thử / bắt chung ngoại lệ 'bắt mọi ngoại lệ có thể có'. Trong trường hợp này, tôi muốn bắt ngoại lệ cụ thể xảy ra khi tệp không tồn tại và tôi cố gắng thực hiện readFileSync.

Xin lưu ý rằng tôi chỉ thực hiện các chức năng đồng bộ hóa khi khởi động trước khi phục vụ các nỗ lực kết nối, do đó, không cần sử dụng các chức năng đồng bộ hóa :-)


1
Bạn cũng có thể sử dụng fs.existsSync()như có thể thấy trong câu trả lời mới của tôi
Francisco Presencia

Câu trả lời:


206

Về cơ bản, fs.readFileSyncném lỗi khi không tìm thấy tệp. Lỗi này là từ Errornguyên mẫu và bị ném bằng cách sử dụng throw, do đó cách duy nhất để bắt là với một try / catchkhối:

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
}

Thật không may, bạn không thể phát hiện ra lỗi nào đã bị ném chỉ bằng cách nhìn vào chuỗi nguyên mẫu của nó:

if (err instanceof Error)

là cách tốt nhất bạn có thể làm và điều này sẽ đúng với hầu hết các lỗi (nếu không phải tất cả). Do đó tôi khuyên bạn nên đi với codetài sản và kiểm tra giá trị của nó:

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

Bằng cách này, bạn chỉ xử lý lỗi cụ thể này và ném lại tất cả các lỗi khác.

Ngoài ra, bạn cũng có thể truy cập thuộc tính của lỗi messageđể xác minh thông báo lỗi chi tiết, trong trường hợp này là:

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

Hi vọng điêu nay co ich.


1
Cảm ơn, đó là thông tin tôi đang tìm kiếm. Tôi chỉ cho rằng đó sẽ là một loại Lỗi cụ thể. Tôi cũng vừa nhận ra rằng tôi đã hiểu sai về cách hoạt động của try / Catch, tôi đã nghĩ rằng bạn có thể bắt được một loại lỗi cụ thể (a la java). Cảm ơn thông tin Golo. :-)
Metalkin

2
Ngoài ra EACCESmã phải được kiểm tra trong câu lệnh if cho trường hợp khi có tệp nhưng không thể đọc được do thiếu quyền
Gergely Toth

21

Tôi thích cách xử lý này. Bạn có thể kiểm tra nếu tệp tồn tại đồng bộ:

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

Lưu ý: nếu chương trình của bạn cũng xóa các tệp, điều này có một điều kiện cuộc đua như được ghi chú trong các bình luận. Tuy nhiên, nếu bạn chỉ viết hoặc ghi đè lên các tập tin, mà không xóa chúng, thì điều này hoàn toàn tốt.


2
bây giờ, fs.existsSync không còn bị phản đối nữa : "Lưu ý rằng fs.exists () không được dùng nữa, nhưng fs.existsSync () thì không."
falkodev 17/2/2017

17
Không tốt hơn chút nào. Điều gì xảy ra nếu tệp bị xóa khỏi đĩa giữa lệnh gọi tồn tại và readFileSync? Mã của bạn hiện có một điều kiện cuộc đua được xây dựng để chờ xảy ra ...
tkarls

2
@tkarls vâng, điều đó hoàn toàn đúng, điều đó đã được viết vào năm 2015 khi tôi vẫn còn học Node.js và nó có một điều kiện chủng tộc. Tuy nhiên, có hai điều cần lưu ý: sự giống nhau của điều kiện cuộc đua này rất nhỏ đến mức về cơ bản nó có thể bị bỏ qua, và điều thứ hai và siêu hạng thứ nhất là tôi sẽ sử dụng thử / bắt với async / chờ đợi hiện tại làm cho mã của tôi linh hoạt hơn trường hợp ngoại lệ "khác" (vì Node thân thiện với ngoại lệ).
Francisco Presencia

1
Điều kiện chủng tộc không quan trọng cho đến khi họ làm. Câu trả lời như thế này là lý do tại sao phần mềm quá lỗi, tại sao bạn cần khởi động lại máy tính thường xuyên như vậy, tại sao có quá nhiều lỗ hổng bảo mật, v.v., v.v. Stack Overflow nên có cờ cho các câu trả lời có hại.
Jonathan Trần

Một nhận xét khác N năm sau, sau khi tìm hiểu thêm một bó (thêm một ghi chú trong câu trả lời). Điều này là hoàn toàn tốt trong bối cảnh của một chương trình hệ thống tệp chỉ ghi, nhưng như đã lưu ý nếu các tệp cũng có thể bị xóa thì điều này có một điều kiện chủng tộc và hiện tại nó không phải là mã mà tôi đang viết (đặc biệt là vì Đồng bộ hóa đó!). Tôi cũng là tác giả của gói filesvới tất cả những gì tôi đã học để làm cho async và thử / bắt dễ dàng hơn.
Francisco Presencia

11

Bạn phải bắt lỗi và sau đó kiểm tra xem đó là loại lỗi gì.

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
}

... làm cho 'ném nhầm;'
drudru

Có cách nào để bắt lỗi tương tự với phiên bản không đồng bộ của chức năng không?
Ki Jéy

1
@ KiJéy Mã Async vượt qua lỗi là đối số đầu tiên của cuộc gọi lại, vì vậy nếu bạn kiểm tra xem bạn có nhận được hành vi tương tự không.
loganfsmyth

4

Tôi sử dụng lambda ngay lập tức được gọi cho các tình huống sau:

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

async phiên bản:

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

Bạn có thể muốn thêm vào bài đăng của mình rằng giải pháp của bạn dành cho ECMAScript 6. Kể từ ngày 01/01/18, không có hỗ trợ nào từ IE với mức độ bao phủ khoảng 77% của việc sử dụng trình duyệt ( caniuse.com/#feat=arrow-fifts ). Tôi tò mò, làm thế nào để bạn phục vụ cho người dùng IE?
Metalkin

2
@Metalskin Webpack + Babel. Tuy nhiên, fslà một mô-đun Node
sdgfsdh

Ahh, tôi không liên lạc được với nút, tôi nghi ngờ rằng nút đó không hỗ trợ ES6 khi tôi đặt câu hỏi (có thể sai). Kinda quên đây cũng là một câu hỏi nút ;-)
Metalkin

đang cập nhật điều này ... fs.readFileAsync()hiện tại fs.readFile() và cũng không nên đặt chức năng async bên trong một lần thử / bắt trong node.js. thử / bắt sẽ không bao giờ gặp lỗi vì nó không đồng bộ. thay vào đó hãy chuyển lỗi trong cuộc gọi lại và xử lý nó tại đó: fs.readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); }); from: nodejs.org/dist/latest-v12.x/docs/api/ Kẻ
KH B

Tôi tin rằng việc thử bắt sẽ được gọi nếu lời hứa bị từ chối và bạn đang chờ lời hứa.
sdgfsdh

0

Thay vào đó, hãy thử sử dụng Async để tránh chặn luồng duy nhất bạn có với NodeJS. Kiểm tra ví dụ này:

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

Sau này có thể sử dụng chức năng async này với thử / bắt từ bất kỳ chức năng nào khác:

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

Chúc mừng mã hóa!


0

Không thể sử dụng cơ chế bắt thử JavaScript của JavaScript để chặn các lỗi được tạo bởi các API không đồng bộ. Một lỗi phổ biến cho người mới bắt đầu là cố gắng sử dụng ném bên trong một cuộc gọi lại lỗi đầu tiên:

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

Điều này sẽ không hoạt động vì hàm gọi lại được truyền cho fs.readFile () được gọi là không đồng bộ. Vào thời điểm cuộc gọi lại được gọi, mã xung quanh, bao gồm cả khối bắt thử, sẽ thoát. Ném một lỗi bên trong cuộc gọi lại có thể làm hỏng quá trình Node.js trong hầu hết các trường hợp. Nếu tên miền được bật hoặc trình xử lý đã được đăng ký với process.on ('unsaughtException'), các lỗi đó có thể bị chặn.

tham khảo: https://nodejs.org/api/errors.html

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.