Rumah  >  Soal Jawab  >  teks badan

Kepentingan sentiasa menangkap kesilapan dalam Janji

Saya menggunakan @typescript-eslint/no-floating-promises peraturan dalam projek saya. Jika saya menulis kod seperti ini, peraturan ini akan mengeluh -

functionReturningPromise()
    .then(retVal => doSomething(retVal));

Ia mahu saya untuk blok Promise 添加一个 catch ini. Ini masuk akal kepada saya jika saya ingin menambah beberapa logik dalam blok pengendalian pengecualian. Walau bagaimanapun, terdapat banyak situasi di mana saya tidak memerlukannya. Saya gembira dengan kesilapan yang dilemparkan. Jadi untuk menyekat ralat yang dilemparkan oleh peraturan ini, saya akhirnya melakukan ini -

functionReturningPromise()
    .then((retVal) => doSomething(retVal))
    .catch((error) => {
        throw error;
    });
Adakah ia benar-benar membuat perbezaan walaupun saya tidak menambah catch 块,error 仍然会以相同的方式抛出(至少在我的控制台输出中看到它)。因此,我不明白显式指定此 catch 块的意义。我错过了什么吗?如果我添加/不添加 catch 块,抛出 error seperti di atas?

P粉590929392P粉590929392213 hari yang lalu362

membalas semua(1)saya akan balas

  • P粉106711425

    P粉1067114252024-03-20 17:42:08

    Pengulas semuanya telah menjawab soalan anda dengan baik - tetapi untuk menggambarkan melalui contoh mengapa ini penting, bayangkan kod berikut:

    Promise.reject();
    setTimeout(() => console.log('hello'), 1000);

    Kod ini kelihatan agak tidak berbahaya - terdapat penolakan janji tanpa operasi yang tidak dikendalikan bahawa program akan dilog 'hello' 1 saat selepas permulaan.

    Dalam penyemak imbas - inilah yang akan berlaku - penyemak imbas akan merekodkan ralat "Penolakan Janji Tidak Ditangkap", tetapi sebaliknya mengabaikannya.

    Walau bagaimanapun, dalam NodeJS (setakat Node v15), penolakan Promise yang tidak dikendalikan adalah ralat keras - bermakna proses akan keluar apabila ralat dikesan!

    Anda boleh mengesahkan ini dengan menjalankan kod dalam Terminal (-e bermaksud "nilai dan jalankan rentetan kod ini")

    $ node -e "Promise.reject(); setTimeout(() => console.log('hello'), 1000)"
    node:internal/process/promises:288
                triggerUncaughtException(err, true /* fromPromise */);
                ^
    
    [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "undefined".] {
      code: 'ERR_UNHANDLED_REJECTION'
    }
    
    Node.js v18.12.1

    Anda boleh lihat 'hello' tidak pernah dicetak kerana proses ditamatkan sebelum 1 saat!

    Untuk mengesahkan bahawa perkara berfungsi seperti yang diharapkan, anda boleh .reject 更改为 .resolve:

    $ node -e "Promise.resolve(); setTimeout(() => console.log('hello'), 1000)"
    hello

    Jadi, jika anda menulis aplikasi NodeJS menggunakan mana-mana versi yang disokong LTS maka anda pasti perlu menangani ralat jika tidak, anda akan menghadapi risiko ranap yang tidak dijangka.

    Jika kod anda hanya berjalan dalam penyemak imbas, anda mungkin tertanya-tanya sama ada anda perlu menangani kegagalan sama sekali - lagipun, pengguna anda tidak melihat konsol, jadi mereka tidak akan tahu apa-apa perkara buruk berlaku, jadi siapa peduli? Dari perspektif "kod sahaja", anda betul - walau bagaimanapun, pengguna anda mahukan maklum balas daripada aplikasi mereka apabila berlaku kesilapan.

    Bayangkan senario berikut - Janji anda menjejaki keputusan panggilan API yang menyerahkan beberapa data yang dimasukkan oleh pengguna dalam aplikasi anda. Jika panggilan API gagal atas sebab tertentu, aplikasi anda harus bertindak balas dengan sewajarnya dan memberitahu pengguna sesuatu telah berlaku.

    Cara alternatif untuk mengendalikannya mungkin bermakna apl anda memaparkan pemutar pemuatan yang tidak terhingga, atau pengguna berpendapat data mereka berjaya diserahkan sedangkan ia sebenarnya tidak. Sama ada cara - ini adalah pengalaman pengguna yang sangat teruk dan rosak!

    Adalah lebih baik untuk melakukan sesuatu yang mudah seperti .catch(e => { throw e }) 这样的事情,你实际上并没有处理错误。当然,这段代码会使 linter 保持沉默 - 但您所做的只是创建一个新的、被拒绝的承诺,该承诺将记录到控制台。相反,您应该以某种方式将错误连接到应用程序的 UI,例如像 .catch(e => {alert(e); throw e }) akhirnya.

    balas
    0
  • Batalbalas