thử {} mà không bắt {} có thể trong JavaScript không?


114

Tôi có một số hàm trả về một cái gì đó hoặc tạo ra một lỗi. Trong một hàm chính, tôi gọi từng hàm này và muốn trả về giá trị được trả về bởi mỗi hàm hoặc chuyển sang hàm thứ hai nếu các hàm đầu tiên gặp lỗi.

Vì vậy, về cơ bản những gì tôi hiện có là:

function testAll() {
    try { return func1(); } catch(e) {}
    try { return func2(); } catch(e) {} // If func1 throws error, try func2
    try { return func3(); } catch(e) {} // If func2 throws error, try func3
}

Nhưng thực ra tôi chỉ trymuốn trả lại nó (tức là nếu nó không gặp lỗi). Tôi không cần catchkhối. Tuy nhiên, mã như try {}không thành công vì nó thiếu một catch {}khối (không sử dụng) .

Tôi đặt một ví dụ trên jsFiddle .

Vì vậy, có cách nào để catchloại bỏ các khối đó trong khi vẫn đạt được hiệu quả tương tự?

Câu trả lời:


4

Không. Bạn phải giữ chúng.

Điều này thực sự có ý nghĩa vì lỗi không nên được bỏ qua một cách im lặng.


16
Trong trường hợp đó những chức năng không nên ném lỗi nhưng trở lại ví dụ nullvà bạn làm điều gì đó giống nhưreturn func1() || func2() || func3();
ThiefMaster

52
Câu trả lời này thực tế không chính xác, bạn có thể có try {}; finally {}như được hiển thị trong stackoverflow.com/a/5764505/68210
Daniel X Moore

4
@DanielXMoore, nếu không có catch (e) {}, ngoại lệ được ném ra func1()sẽ ngăn không func2()được thử.
binki

65
Đôi khi, việc bắt được trống cũng có ý nghĩa hoàn hảo, vì vậy tôi không đồng ý với lập luận của bạn.
Petr Peller

8
Câu trả lời này thực tế không chính xác và gây hiểu lầm. Bạn nói "Nó thực sự có ý nghĩa", nhưng bạn đã nhầm, nó chỉ có ý nghĩa trong một số trường hợp chứ không phải những trường hợp khác. Đó là một ví dụ tuyệt vời về một câu trả lời khủng khiếp được chấp nhận không thể giải thích được. Có nhiều trường hợp asyncđôi khi không có khối bắt, chẳng hạn như trong một hàm. Việc bị buộc bởi ngôn ngữ javascript để tạo ra catchcác khối trống rõ ràng là vô nghĩa.
YungGun

236

Một lần thử không có mệnh đề bắt sẽ gửi lỗi của nó đến lần bắt cao hơn tiếp theo hoặc cửa sổ, nếu không có lệnh bắt nào được xác định trong lần thử đó.

Nếu bạn không có hàm bắt , biểu thức try yêu cầu mệnh đề cuối cùng .

try {
    // whatever;
} finally {
    // always runs
}

Vì vậy, cách tốt nhất sẽ là viết một cái gì đó như thế try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}nào?
dùng2284570

1
Nhận xét trên không trả lời chính xác OP vì anh ta không muốn chạy chức năng 2 nếu chức năng 1 thành công.
Andrew Steitz


Cảm ơn bạn, đó là những gì tôi cần :-) Sẽ thực sự tuyệt vời nếu nó cũng hoạt động mà không cần thử {} Ý tôi là: async () => {allowWorkInProgress () await pipeStep1 () await pipeStep2 () ... cuối cùng là {stopIndicator ( )}} Nó sẽ được rõ ràng rằng toàn bộ chức năng có nghĩa là ;-) những khối try rất xấu xí đó ...
Lenny

35

Có thể có một khối bắt trống, không có biến lỗi, bắt đầu với ES2019 . Đây được gọi là liên kết bắt tùy chọn và được triển khai trong V8 v6.6, phát hành vào tháng 6 năm 2018 . Tính năng này đã có từ Node 10 , Chrome 66 , Firefox 58 , Opera 53Safari 11.1 .

Cú pháp được hiển thị bên dưới:

try {
  throw new Error("This won't show anything");
} catch { };

Bạn vẫn cần một catchkhối, nhưng nó có thể trống và bạn không cần chuyển bất kỳ biến nào. Nếu bạn không muốn một khối bắt nào cả, bạn có thể sử dụng dấu try/ finally, nhưng lưu ý rằng nó sẽ không nuốt lỗi như một lệnh bắt trống.

try {
  throw new Error("This WILL get logged");
} finally {
  console.log("This syntax does not swallow errors");
}


2
câu trả lời này là mới nhất! về thứ tự thực hiện, 1. nó thử trykhối. 2. Bắt lỗi. 3. Thực thi finallykhối. 4. Ném lỗi. Điều này có chính xác?
Helsont

Cảm ơn @helsont. Đối với thứ tự thực thi trong mẫu mã thứ hai, tôi không chắc người ta có thể biết liệu lỗi có được bắt và ném lại hay chỉ (có thể) chỉ đơn giản là được ném và không bị bắt ngay từ đầu (vì không có catch). Bao quanh toàn bộ mã bằng một dấu try/ kháccatch và bạn sẽ có thể bắt This WILL get loggedlỗi.
Dan Dascalescu

Bây giờ trông rất sạch sẽ. Cám ơn vì đã chia sẻ!
LeOn - Han Li

10

Không, catch(hoặc finally) là trybạn của và luôn ở đó như một phần của thử / bắt .

Tuy nhiên, hoàn toàn hợp lệ nếu để chúng trống, như trong ví dụ của bạn.

Trong các nhận xét trong mã ví dụ của bạn ( Nếu func1 ném lỗi, hãy thử func2 ), có vẻ như điều bạn thực sự muốn làm là gọi hàm tiếp theo bên trong catchkhối của khối trước đó.


1
Bạn hoàn toàn đúng. Tuy nhiên, nếu try {...}; try {...}có thể có mã giống như vậy, thì ý nghĩa của mã có thể rõ ràng hơn (hãy thử cách đầu tiên, nếu không hãy thử cách thứ hai).
pimvdb

Về chỉnh sửa của bạn: Trong ví dụ JSFiddle, hàm thứ hai trả về một thứ gì đó, vậy hàm thứ ba có thực sự được đánh giá trong trường hợp đó không? Tôi nghĩ rằng một returntuyên bố dừng bất cứ điều gì đến sau nó.
pimvdb

@pimvdb Xin lỗi, tôi chưa kiểm tra fiddle. returnsẽ làm cho chức năng trở lại sớm. Tôi sẽ cập nhật câu trả lời của tôi.
alex

1
Câu trả lời này thực tế không chính xác, bạn có thể có try {}; finally {}như được hiển thị trong stackoverflow.com/a/5764505/68210
Daniel X Moore

1
@DanielXMoore Chắc chắn là vậy, nhưng finally{}về cơ bản vẫn theo tinh thần như catch{}. Tôi sẽ cập nhật câu trả lời.
alex

6

Tôi sẽ không khuyên bạn nên thử cuối cùng mà không nắm bắt được, bởi vì nếu cả khối try và cuối cùng là lỗi khối ném, lỗi được đưa ra trong mệnh đề cuối cùng sẽ nổi lên và lỗi của khối thử được bỏ qua, trong thử nghiệm của riêng tôi:

try {
  console.log('about to error, guys!');
  throw new Error('eat me!');
} finally {
  console.log ('finally, who cares');
  throw new Error('finally error');
}

Kết quả:

>     about to error, guys!
>     finally, who cares
>     .../error.js:9
>         throw new Error('finally error');
>         ^
>     
>     Error: finally error

1

Chúng đi cùng nhau trong mọi ngôn ngữ mà tôi biết có chúng (JavaScript, Java, C #, C ++). Đừng làm vậy.


1
Kỳ lạ là tôi đã bị từ chối vào năm năm sau khi nó nói điều tương tự như những câu trả lời khác ở đây. Của tôi dường như là người duy nhất bị phản đối. Người điều hành, hãy lưu ý.
duffymo

Tcl có rất thuận tiện xây dựng đơn từcatch {my code}
MKaama


Tại sao? Cảm thấy vô ích, trừ khi nó thử / cuối cùng.
duffymo

1

Tôi quyết định xem xét vấn đề được trình bày ở một góc độ khác.

Tôi đã có thể xác định một cách để cho phép chặt chẽ mẫu mã được yêu cầu trong khi giải quyết một phần đối tượng lỗi chưa được xử lý được liệt kê bởi một người bình luận khác.

mã có thể được nhìn thấy @ http://jsfiddle.net/Abyssoft/RC7Nw/4/

try: catch được đặt trong vòng lặp for cho phép rơi qua một cách duyên dáng. trong khi có thể lặp qua tất cả các chức năng cần thiết. khi cần xử lý lỗi rõ ràng là cần sử dụng mảng hàm bổ sung. trong mảng chẵn của lỗi và mảng chức năng với phần tử trình xử lý lỗi không phải là một hàm, lỗi được kết xuất cho bảng điều khiển.

Theo yêu cầu của stackoverflow ở đây là mã nội tuyến [được chỉnh sửa để tuân thủ JSLint (xóa khoảng trắng ở đầu để xác nhận), cải thiện khả năng đọc]

function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }

// ctr = Code to Run <array>, values = values <array>, 
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
    "use strict";
    var cb; // cb = code block counter
    for (cb in ctr) {
        if (ctr.hasOwnProperty(cb)) {
            try {
                return ctr[cb](values[cb]);
            } catch (e) {
                if (typeof eh[cb] === "function") {
                    eh[cb](e);
                } else {
                    //error intentionally/accidentially ignored
                    console.log(e);
                }
            }
        }
    }
    return false;
}

window.alert(testAll([func1, func2, func3], [], []));

Các bác sĩ cho biết thêm:


1

Nếu bạn chỉ muốn các chức năng 2 và 3 kích hoạt nếu xảy ra lỗi tại sao bạn không đưa chúng vào khối bắt?

function testAll() {
  try {
    return func1();
  } catch(e) {
    try {
      return func2();
    } catch(e) {
      try {
        return func3();
      } catch(e) {
        // LOG EVERYTHING FAILED
      }
    }
  }
}

0

Tôi tin rằng bạn cần sử dụng chức năng trợ giúp như:

function tryIt(fn, ...args) {
    try {
        return fn(...args);
    } catch {}
}

và sử dụng nó như:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);


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.