Saya kesulitan memahami perbedaan antara menempatkan .catch
SEBELUMNYA dan SETELAH kemudian dalam janji bertingkat.
Alternatif 1:
test1Async(10).then((res) => {
return test2Async(22)
.then((res) => {
return test3Async(100);
}).catch((err) => {
throw "ERROR AFTER THEN";
});
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
Alternatif 2:
test1Async(10).then((res) => {
return test2Async(22)
.catch((err) => {
throw "ERROR BEFORE THEN";
})
.then((res) => {
return test3Async(100);
});
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
Perilaku masing-masing fungsi adalah sebagai berikut, test1 gagal jika nomor <0
test2 gagal jika nomor > 10
dan test3 gagal jika nomor tidak 100
. Dalam kasus ini test2 hanya gagal.
Saya mencoba menjalankan dan membuat test2Async gagal, baik SEBELUM dan SETELAH kemudian berperilaku dengan cara yang sama dan itu tidak menjalankan test3Async. Adakah yang bisa menjelaskan kepada saya perbedaan utama dalam menempatkan tangkapan di tempat yang berbeda?
Di setiap fungsi saya console.log('Running test X')
untuk memeriksa apakah itu dijalankan.
Pertanyaan ini muncul karena utas sebelumnya yang saya posting Bagaimana mengubah panggilan balik bersarang menjadi janji? . Saya pikir ini adalah masalah yang berbeda dan layak untuk memposting topik lain.
sumber
Jawaban:
Jadi, pada dasarnya Anda bertanya apa perbedaan antara keduanya (di mana
p
janji dibuat dari beberapa kode sebelumnya):dan
Ada perbedaan baik ketika p menyelesaikan atau menolak, tetapi apakah perbedaan itu penting atau tidak tergantung pada apa yang dilakukan kode di dalam
.then()
atau.catch()
penangan.Apa yang terjadi jika
p
teratasi:Dalam skema pertama, saat
p
diselesaikan,.then()
penangan dipanggil. Jika.then()
penangan tersebut mengembalikan nilai atau janji lain yang akhirnya terselesaikan, maka.catch()
penangan dilewati. Namun, jika.then()
penangan melempar atau mengembalikan sebuah janji yang pada akhirnya menolak, maka.catch()
penangan akan mengeksekusi penolakan dalam janji aslip
, tetapi juga kesalahan yang terjadi pada.then()
penangan.Dalam skema kedua, saat
p
diselesaikan,.then()
penangan dipanggil. Jika.then()
penangan tersebut melempar atau mengembalikan sebuah janji yang pada akhirnya ditolak, maka.catch()
penangan tidak dapat menangkapnya karena itu sebelum itu dalam rantai.Jadi, itulah perbedaan # 1. Jika
.catch()
pawang AFTER, maka itu juga bisa menangkap kesalahan di dalam.then()
pawang.Apa yang terjadi jika
p
ditolak:Sekarang, pada skema pertama, jika promise
p
ditolak, maka.then()
handler dilewati dan.catch()
handler akan dipanggil seperti yang Anda harapkan. Apa yang Anda lakukan di.catch()
pawang menentukan apa yang dikembalikan sebagai hasil akhir. Jika Anda baru saja mengembalikan nilai dari.catch()
penangan atau mengembalikan janji yang akhirnya terselesaikan, rantai janji akan beralih ke status terselesaikan karena Anda "menangani" kesalahan dan mengembalikan secara normal. Jika Anda membuang atau mengembalikan janji yang ditolak di.catch()
pawang, janji yang dikembalikan tetap ditolak.Pada skema kedua, jika promise
p
ditolak, maka.catch()
handler dipanggil. Jika Anda mengembalikan nilai normal atau janji yang pada akhirnya.catch()
diselesaikan dari penangan (dengan demikian "menangani" kesalahan), maka rantai janji beralih ke keadaan terselesaikan dan.then()
penangan setelah.catch()
akan dipanggil.Jadi itulah perbedaan # 2. Jika
.catch()
penangannya SEBELUM, maka ia dapat menangani kesalahan dan memungkinkan.then()
penangan untuk tetap dipanggil.Kapan menggunakan yang:
Gunakan skema pertama jika Anda menginginkan hanya satu
.catch()
penangan yang dapat menangkap kesalahan baik di promise aslip
atau di.then()
penangan dan penolakan darip
harus melewati.then()
penangan.Gunakan skema kedua jika Anda ingin dapat menangkap error dalam promise asli
p
dan mungkin (bergantung pada kondisi), izinkan rantai promise untuk dilanjutkan setelah diselesaikan, sehingga menjalankan.then()
penangan.Pilihan lainnya
Ada satu opsi lain untuk menggunakan kedua callback yang dapat Anda teruskan
.then()
seperti:Ini menjamin bahwa hanya satu dari
fn1
ataufn2
akan pernah dipanggil. Jika berhasilp
, makafn1
akan dipanggil. Jikap
ditolak, makafn2
akan dipanggil. Tidak ada perubahan hasil yangfn1
dapat membuatfn2
dipanggil atau sebaliknya. Jadi, jika Anda ingin benar-benar memastikan bahwa hanya satu dari dua penangan Anda yang dipanggil terlepas dari apa yang terjadi pada penangan itu sendiri, maka Anda dapat menggunakanp.then(fn1, fn2)
.sumber
.then()
dan.catch()
, yang Anda jawab. Selain itu Anda memberikan beberapa tip kapan harus menggunakan urutan yang mana, yang menurut saya tepat untuk menyebutkan opsi ketiga, yaitu meneruskan sukses dan penanganan kesalahan ke .then () . Dalam kasus itu, paling banyak satu penangan akan dipanggil.Promise.reject(new Error("F")).then(x => x).catch(e => {console.log(e); return [1]}).then(console.log)
danPromise.resolve([2]).then(x => x).catch(e => [1]).then(console.log)
.then(this.setState({isModalOpen: false}))
. Anda tidak meneruskan referensi fungsi.then()
agar kode di dalam tanda kurung segera dieksekusi (sebelum janji diselesaikan). Seharusnya begitu.then(() => this.setState({isModalOpen: false}))
.Jawaban jfriend00 sangat bagus, tetapi saya pikir akan menjadi ide yang baik untuk menambahkan kode sinkron analog.
mirip dengan sinkron:
Jika
iMightThrow()
tidak melempar,then()
akan dipanggil. Jika ia melempar (atau jikathen()
dirinya sendiri melempar), makahandleCatch()
akan dipanggil. Perhatikan bagaimanacatch
blok tidak memiliki kendali atas pemanggilan atau tidakthen
.Di samping itu,
mirip dengan sinkron:
Dalam hal ini, jika
iMightThrow()
tidak melempar, makathen()
akan dieksekusi. Jika tidak melempar, maka akan terserah untukhandleCatch()
memutuskan apakahthen()
dipanggil, karena jikahandleCatch()
ditarik kembali, makathen()
tidak akan dipanggil, karena pengecualian akan segera dilemparkan ke pemanggil. JikahandleCatch()
dapat menangani masalah dengan anggun, makathen()
akan dipanggil.sumber
then()
dalamfinally{...}
then()
difinally{...}
, akan tidak tidak benar disebut bahkan jikahandleCatch()
melempar? Perlu diingat bahwa tujuan saya adalah untuk menunjukkan kode sinkron yang analog, bukan untuk menyarankan cara penanganan pengecualian yang berbeda