ลองใช้ JavaScript {} without catch {} ได้ไหม


115

ฉันมีฟังก์ชั่นหลายอย่างที่ส่งคืนบางอย่างหรือส่งข้อผิดพลาด ในฟังก์ชันหลักฉันเรียกสิ่งเหล่านี้และต้องการส่งคืนค่าที่ส่งคืนโดยแต่ละฟังก์ชันหรือไปที่ฟังก์ชันที่สองหากฟังก์ชันแรกเกิดข้อผิดพลาด

โดยพื้นฐานแล้วสิ่งที่ฉันมีอยู่คือ:

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
}

แต่จริงๆแล้วฉันต้องการtryส่งคืนเท่านั้น(เช่นถ้ามันไม่เกิดข้อผิดพลาด) ฉันไม่ต้องการcatchบล็อก อย่างไรก็ตามรหัสเช่นtry {}ล้มเหลวเนื่องจากไม่มีcatch {}บล็อก(ไม่ได้ใช้)

ฉันใส่ตัวอย่างใน jsFiddle

ดังนั้นมีวิธีใดบ้างที่จะcatchลบบล็อกเหล่านั้นออกไปในขณะที่ได้ผลเช่นเดียวกัน?

คำตอบ:


3

ไม่คุณต้องเก็บไว้

สิ่งนี้สมเหตุสมผลจริง ๆ เนื่องจากข้อผิดพลาดไม่ควรถูกเพิกเฉยเลย


16
ในกรณีนี้ฟังก์ชั่นเหล่านั้นไม่ควรส่งข้อผิดพลาด แต่กลับเช่นnullและคุณทำสิ่งที่ชอบreturn func1() || func2() || func3();
ThiefMaster

53
คำตอบนี้ไม่ถูกต้องตามความเป็นจริงคุณสามารถมีtry {}; finally {}ดังที่แสดงในstackoverflow.com/a/5764505/68210
Daniel X Moore

4
@DanielXMoore หากไม่มีcatch (e) {}ข้อยกเว้นที่เกิดขึ้นfunc1()จะป้องกันไม่ให้func2()ถูกพยายาม
binki

67
บางครั้งมันก็สมเหตุสมผลดีที่จะมีการจับที่ว่างเปล่าดังนั้นฉันจึงไม่เห็นด้วยกับการโต้แย้งของคุณ
Petr Peller

9
คำตอบนี้ไม่ถูกต้องตามความเป็นจริงและทำให้เข้าใจผิด "มันสมเหตุสมผล" ที่คุณพูด แต่คุณคิดผิดมันสมเหตุสมผลในบางกรณีเท่านั้นไม่ใช่เรื่องอื่น เป็นตัวอย่างที่ดีของคำตอบที่น่ากลัวซึ่งได้รับการยอมรับอย่างลึกลับ มีหลายกรณีที่เหมาะสมที่จะไม่มีการดักจับเช่นในasyncฟังก์ชันบางครั้ง การถูกบังคับโดยภาษาจาวาสคริปต์ให้สร้างcatchบล็อกว่างเปล่านั้นไม่มีจุดหมายอย่างชัดเจน
YungGun

239

การ ลองโดยไม่มีประโยคcatchจะส่งข้อผิดพลาดไปยังcatch ที่สูงขึ้นถัดไปหรือหน้าต่างหากไม่มีการกำหนด catch ไว้ภายในการลองนั้น

หากคุณไม่มีสิ่งที่จับได้นิพจน์ try ต้องมีประโยคสุดท้าย

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

ดังนั้นวิธีที่ดีที่สุดคือเขียนอะไรเช่นtry { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570

1
ความคิดเห็นข้างบนไม่ได้ตอบ OP อย่างถูกต้องเพราะเขาไม่ต้องการเรียกใช้ฟังก์ชัน 2 หากฟังก์ชัน 1 สำเร็จ
Andrew Steitz

2
ทราบว่าลองโดยไม่ต้องจับไม่ข้อผิดพลาดที่ไม่กลืน
Dan Dascalescu

ขอบคุณนั่นคือสิ่งที่ฉันต้องการ :-) มันจะยอดเยี่ยมมากถ้ามันใช้งานได้โดยไม่ต้องลอง {} ฉันหมายถึง: async () => {indicWorkInProgress () รอ pipelineStep1 () รอ pipelineStep2 () ... ในที่สุด {stopIndicator ( )}} เป็นที่ชัดเจนว่าฟังก์ชั่นทั้งหมดมีความหมาย ;-) ลองบล็อกเหล่านั้นน่าเกลียดมากที่นั่น ...
Lenny

36

มันเป็นไปได้ที่จะมีการจับบล็อกที่ว่างเปล่าโดยไม่ต้องตัวแปรข้อผิดพลาดที่เริ่มต้นด้วยES2019 นี้เรียกว่าการจับตัวเลือกที่มีผลผูกพันและถูกนำมาใช้ในV8 v6.6 ปล่อยมิถุนายน 2018 คุณลักษณะที่ได้รับมีตั้งแต่โหนด 10 , Chrome 66 , Firefox 58 , Opera 53และSafari 11.1

ไวยากรณ์ดังแสดงด้านล่าง:

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

คุณยังต้องการcatchบล็อก แต่อาจว่างเปล่าและคุณไม่จำเป็นต้องส่งผ่านตัวแปรใด ๆ หากคุณไม่ต้องการบล็อกการจับเลยคุณสามารถใช้try/ finallyแต่โปรดทราบว่าจะไม่กลืนข้อผิดพลาดเหมือนการจับที่ว่างเปล่า

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


3
คำตอบนี้เป็นข้อมูลล่าสุด! ในแง่ของคำสั่งดำเนินการ 1. มันพยายามtryบล็อก 2. จับข้อผิดพลาด 3. ดำเนินการfinallyบล็อก 4. โยนข้อผิดพลาด ถูกต้องหรือไม่
helsont

ขอบคุณ @helsont สำหรับคำสั่งดำเนินการในตัวอย่างรหัสที่สองฉันไม่แน่ใจว่ามีใครสามารถบอกได้ว่าข้อผิดพลาดถูกจับและโยนใหม่หรือ (อาจ) เพียงแค่โยนและไม่ถูกจับตั้งแต่แรก (เนื่องจากไม่มีcatch) ล้อมรอบรหัสทั้งหมดด้วยรหัสอื่นtry/catchและคุณจะสามารถจับThis WILL get loggedข้อผิดพลาดได้
Dan Dascalescu

ดูสะอาดขึ้นเยอะเลยตอนนี้ ขอบคุณสำหรับการแบ่งปัน!
LeOn - Han Li

10

Nope, catch(หรือfinally) เป็นtry'เพื่อนและมักจะมีเป็นส่วนหนึ่งของลอง / จับ

อย่างไรก็ตามมันถูกต้องอย่างสมบูรณ์ที่จะปล่อยให้ว่างเปล่าเช่นในตัวอย่างของคุณ

ในความคิดเห็นในโค้ดตัวอย่างของคุณ ( หาก func1 แสดงข้อผิดพลาดให้ลอง func2 ) ดูเหมือนว่าสิ่งที่คุณต้องการจะทำจริงๆคือเรียกใช้ฟังก์ชันถัดไปภายในcatchบล็อกก่อนหน้านี้


1
คุณถูกต้อง อย่างไรก็ตามหากรหัสต้องการtry {...}; try {...}เป็นไปได้ความหมายของรหัสอาจชัดเจนกว่า (ลองข้อแรกหรือลองข้อที่สอง)
pimvdb

เกี่ยวกับการแก้ไขของคุณ: ในตัวอย่าง JSFiddle ฟังก์ชันที่สองส่งคืนบางสิ่งดังนั้นฟังก์ชันที่สามจึงถูกประเมินในกรณีนั้นจริงหรือ ฉันคิดว่าreturnคำสั่งจะหยุดทุกสิ่งที่ตามมา
pimvdb

@pimvdb ขออภัยไม่ได้ตรวจสอบซอ returnจะทำให้ฟังก์ชันกลับมาก่อนเวลาอันควร ฉันจะอัปเดตคำตอบของฉัน
alex

1
คำตอบนี้ไม่ถูกต้องตามความเป็นจริงคุณสามารถมีtry {}; finally {}ดังที่แสดงในstackoverflow.com/a/5764505/68210
Daniel X Moore

1
@DanielXMoore แน่นอนว่ามันเป็น แต่finally{}โดยพื้นฐานแล้วอยู่ในจิตวิญญาณเดียวกันกับcatch{}. ฉันจะอัปเดตคำตอบ
alex

6

ฉันจะไม่แนะนำให้ลองโดยไม่ต้องจับในที่สุดเพราะถ้าทั้ง try block และ block throw error ในที่สุดข้อผิดพลาดที่เกิดขึ้นในประโยคสุดท้ายจะถูกทำให้เป็นฟองและข้อผิดพลาดของ try block จะถูกละเว้นในการทดสอบของฉันเอง:

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

ผลลัพธ์:

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

1

ฉันตัดสินใจที่จะมองปัญหาที่นำเสนอจากมุมที่ต่างออกไป

ฉันสามารถกำหนดวิธีที่จะอนุญาตอย่างใกล้ชิดสำหรับรูปแบบรหัสที่ร้องขอในขณะที่อยู่ในส่วนที่ระบุถึงออบเจ็กต์ข้อผิดพลาดที่ไม่ได้จัดการซึ่งแสดงโดยผู้แสดงความคิดเห็นรายอื่น

รหัสสามารถมองเห็นได้ @ http://jsfiddle.net/Abyssoft/RC7Nw/4/

ลอง: จับวางไว้ในห่วงเพื่อให้สามารถตกลงไปได้อย่างสง่างาม ในขณะที่สามารถวนซ้ำผ่านฟังก์ชั่นทั้งหมดที่จำเป็น เมื่อจำเป็นต้องจัดการข้อผิดพลาดอย่างชัดเจนจะใช้อาร์เรย์ฟังก์ชันเพิ่มเติม ในอาร์เรย์ข้อผิดพลาดและฟังก์ชันที่มีองค์ประกอบตัวจัดการข้อผิดพลาดไม่ใช่ฟังก์ชันข้อผิดพลาดจะถูกถ่ายโอนไปยังคอนโซล

ตามข้อกำหนดของ stackoverflow นี่คือโค้ดแบบอินไลน์ [แก้ไขเพื่อให้สอดคล้องกับ JSLint (ลบช่องว่างนำหน้าเพื่อยืนยัน) ปรับปรุงความสามารถในการอ่าน]

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], [], []));


1

หากคุณต้องการให้ฟังก์ชัน 2 และ 3 เริ่มทำงานหากเกิดข้อผิดพลาดเหตุใดคุณจึงไม่วางไว้ในบล็อก catch

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

0

พวกเขาไปด้วยกันในทุกภาษาที่ฉันรู้ว่ามี (JavaScript, Java, C #, C ++) อย่าทำ


1
แปลกที่ของฉันถูกลดคะแนนในห้าปีต่อมาเมื่อมันพูดในสิ่งเดียวกันกับคำตอบอื่น ๆ ที่นี่ ฉันดูเหมือนจะเป็นคนเดียวที่ถูกลดคะแนน ผู้ดูแลโปรดทราบ
duffymo

Tcl มีโครงสร้างคำเดียวที่สะดวกมากcatch {my code}
MKaama

เริ่มต้นด้วย ES2019 จับผูกพันเป็นตัวเลือก
Dan Dascalescu

ทำไม? รู้สึกไร้ประโยชน์เว้นแต่จะพยายาม / ในที่สุด
duffymo

0

ฉันเชื่อว่าคุณต้องใช้ฟังก์ชันตัวช่วยเช่น:

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

และใช้มันเช่น:

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

-3

ลองจับเป็นเหมือน 2 ด้านของเหรียญเดียว เป็นไปไม่ได้เลยหากไม่ได้ลอง


5
คำตอบนี้ไม่ถูกต้องตามความเป็นจริงคุณสามารถมีได้try {}; finally {}ดังที่แสดงในstackoverflow.com/a/5764505/68210
Daniel X Moore

และเริ่มต้นด้วย ES2019 จับผูกพันเป็นตัวเลือก
Dan Dascalescu

-3

ตั้งแต่ES2019คุณสามารถใช้ได้อย่างง่ายดายtry {}โดยไม่ต้องcatch {}:

try {
  parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}

สำหรับข้อมูลเพิ่มเติมโปรดตอบกลับข้อเสนอของ Michael Ficcara


1
ไม่catchจำเป็นต้องใช้มันเป็นเพียงการผูกที่ไม่จำเป็น ...
chipit24
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.