<p>Pengecualian yang ditangani oleh dva2 onError masih dilemparkan</p>

Dibuat pada 15 Sep 2017  ·  11Komentar  ·  Sumber: dvajs/dva

Setelah onError menangkap pengecualian, pengecualian masih dilemparkan

Dalam keadaan normal, jika pengecualian terjadi selama pemrosesan efek, itu akan ditangkap oleh onError yang didaftarkan oleh dva, dan pemrosesan umum dapat dilakukan di sini, yang sangat mudah digunakan.

Namun, setelah memutakhirkan dva2, saya menemukan sebuah fenomena (tidak muncul di dva1, atau situasi lain tidak diperhatikan pada saat itu) Ketika pengecualian dipicu, onError akan dimasukkan, tetapi pengecualian akan dilemparkan secara normal, menyebabkan konsol untuk menampilkan kesalahan.

Saya bukan front-end penuh waktu. Saya tidak tahu apakah situasi di atas disengaja. Jika ya, mohon beri tahu jika ada cara yang baik untuk mencegah pengecualian dilemparkan saat onError sedang diproses.

Kode untuk mereproduksi masalah: (Harap berikan kode atau langkah yang dapat direproduksi)

dva onError:
```skrip java
onError: (e) => {
console.log('onError', e)
}

any effect: 
```java script
() => { throw Error('any error')}

Perilaku yang diharapkan: (efek normal yang diharapkan)

Defaultnya adalah menangani secara diam-diam setelah penangkapan, tidak lagi melempar, jika Anda perlu melempar pengecualian lagi, Anda dapat melemparkannya sendiri di onError

Perilaku aktual: (efek aktual)

cetak konsol:
Kesalahan onError: kesalahan apa pun ...

dan kesalahan konsol:
Tidak tertangkap (dalam janji) Kesalahan: kesalahan apa pun

Versi paket yang digunakan: (versi perpustakaan mana yang bermasalah)

dva 2.0.1

enhancement faq

Komentar yang paling membantu

Kembali benar dan salah juga terasa agak aneh. Dengan cara ini, berikan metode preventDefault untuk mencegah operasi penolakan berikutnya setelah eksekusi.

onError(e) {
  e.preventDefault();
}

Semua 11 komentar

Memeriksanya.

Alasannya adalah bahwa di dva@2 , jika tindakan pengiriman adalah Efek, Janji akan dikembalikan. Dengan cara ini, panggilan balik pengiriman dapat ditangani di Component (#175 ), dan karena Component perlu menangani skenario penolakan Promise, kesalahan di sini tidak dapat diatasi oleh onError. .

dispatch({
  type: 'effectAction'
})
  .then(() => {})
  .catch(() => {})

Kemudian Promise Rejection yang tidak tertangkap dikeluarkan melalui console.error, tetapi tidak menimbulkan kesalahan, sehingga tidak akan ditangkap oleh window.onerror, dan tidak berpengaruh pada pengguna.

Jika Anda tidak ingin melihat baris kesalahan ini, ada dua cara:

1> Tambahkan .catch ke efek dispatch() .catch

dispatch().catch(err => {});

2> Pantau secara global kejadian unhandledrejection dan cegah agar tidak dicetak melalui console.error.

window.addEventListener("unhandledrejection", function (event) {
  event.preventDefault();
});

Terima kasih atas jawabannya, dampaknya terhadap pengguna tidak besar, terutama karena ada banyak masalah yang menyakitkan dalam proses pengembangan, seperti kode status http 4xx , akan mencetak informasi pengecualian, dan kami menggunakannya dalam bereaksi skenario asli Dalam mode pengembangan, console.error akan benar-benar memainkan kotak kuning...

Adapun dua metode pemrosesan ini:

  1. Menambahkan catch berarti semua kemungkinan kelainan memerlukan perawatan khusus, atau jika Anda secara aktif menyesuaikan onError , Anda perlu mengulang kode, yang terasa kurang umum
  2. rn Tidak yakin apakah ada sesuatu yang mirip dengan event yang dapat menelan pengecualian

Dengan berani mengusulkan ide setengah matang, di onError Masuk resolve dan reject objek, onError untuk memutuskan bagaimana menangani internal, atau dengan onError Nilai kembalian

Anda tidak dapat melakukannya di onError Waktu di Promise dan saga berbeda, yang akan menyebabkan onError terpicu dua kali. Apa pendapat Anda tentang menambahkan onDispatchError ?

Balasannya cepat sekali, memang kalau di onError , reject akan masuk onError ...
Jika ada onDispatchError , itu hanya digunakan untuk memproses action untuk error , jika benar-benar layak, jika Anda perlu membuangnya, cukup reject , dan masukkan kembali catch ditulis sendiri onError
Dengan kata lain, error ini hanya akan memasukkan onDispatchError , dan tidak akan memasukkan dua error handler kan?

  function *sagaWithCatch(...args) {
    try {
      yield sagaEffects.put({ type: `${key}${NAMESPACE_SEP}@@start` });
      const ret = yield effect(...args.concat(createEffects(model)));
      yield sagaEffects.put({ type: `${key}${NAMESPACE_SEP}@@end` });
      resolve(key, ret);
    } catch (e) {
      onError(e);
      reject(key, e);
    }
  }

Masalahnya adalah kode ini, kan? Saya memeriksa masalah ini dengan tuan rumah, dan secara pribadi berpikir ada dua cara untuk dipertimbangkan.

  // 传 reject 进 onError
  function *sagaWithCatch(...args) {
    try {
      yield sagaEffects.put({ type: `${key}${NAMESPACE_SEP}@@start` });
      const ret = yield effect(...args.concat(createEffects(model)));
      yield sagaEffects.put({ type: `${key}${NAMESPACE_SEP}@@end` });
      resolve(key, ret);
    } catch (e) {
      onError(e, reject.bind(null, key, e)); // 把 redux middleware 产生的 promise 的 reject 给 onError ,由 onError 决定要不要触发这个 promise 的 catch 链
      // 甚至可以把 resolve 都传进去,可以做到部分 error 处理后仍然正常执行 dispatch 的 then ,但感觉太奇怪了
    }
  }

  // onError 返回一个 true/false
  function *sagaWithCatch(...args) {
    try {
      yield sagaEffects.put({ type: `${key}${NAMESPACE_SEP}@@start` });
      const ret = yield effect(...args.concat(createEffects(model)));
      yield sagaEffects.put({ type: `${key}${NAMESPACE_SEP}@@end` });
      resolve(key, ret);
    } catch (e) {
      const handled = onError(e);
      if (!handled) reject(key, e); // onError 返回是否要继续抛出 error
    }
  }

Kembali benar dan salah juga terasa agak aneh. Dengan cara ini, berikan metode preventDefault untuk mencegah operasi penolakan berikutnya setelah eksekusi.

onError(e) {
  e.preventDefault();
}

@sorrycc 👍 Nah, ini memang lebih masuk akal. Lagi pula, onError seharusnya tidak mengembalikan nilai secara semantik, dan arti spesifik dari benar/salah dari nilai yang dikembalikan tidak jelas.

Di tunggu rilisnya

Halo penulis @sorrycc , ada pertanyaan kecil, saya lebih bingung, saya memproses request.js secara seragam, kode status bukan 2xx, dan 3xx dioperasikan secara seragam oleh reject , dan catch ditentukan dalam pengiriman try catch dalam efeknya untuk menangkap pengecualian. Saya pikir proses pengecualian pertama-tama akan melewati pengiriman catch , ketika saya tidak memiliki catch Saya berjalan ke onError . Tapi sekarang saya langsung ke onError , yang saya tahu adalah bahwa Anda dapat pergi ke try catch berlaku, dan melakukan operasi reject di catch Selesaikan kebutuhan saya , tetapi setiap efek terasa aneh. Apakah perilaku ini memenuhi harapan Anda? Jika demikian, apa alasannya?

@ jinyang1994 Apakah sudah terpecahkan sekarang?

@jinyang1994 @dyf19118

Alasannya adalah bahwa di dva@2 , jika tindakan pengiriman adalah Efek, Janji akan dikembalikan. Dengan cara ini, panggilan balik pengiriman dapat ditangani di Component (#175 ), dan karena Component perlu menangani skenario penolakan Promise, kesalahan di sini tidak dapat diatasi oleh onError. .

Mengacu pada hal di atas, jika pengecualian yang dilempar ke dalam efek tidak tertangkap, onError akan dieksekusi, dan kemudian Janji yang dikembalikan oleh pengiriman akan diproses. Jika err. preventDefault() dipanggil di onError, tangkapan pengiriman berikutnya tidak akan dieksekusi.

Mengirimkan efek, ada masalah dengan kode bisnis di dalamnya, saya tidak mencoba menangkap efeknya, dan halaman langsung macet. Saya ingin menangkap kesalahan melalui kenyamanan global tingkat atas untuk mencegah halaman mogok.

  • Sekarang saya menambahkan kesalahan tangkapan global: sebagai berikut
window.addEventListener("unhandledrejection", function (event) {
 console.log('err.....,,,,', event)
  event.preventDefault();
});

Kesalahan terdeteksi, tetapi halaman tetap macet. Bagaimana cara mencegah halaman mogok?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat