Apakah Anda perlu berhenti berlangganan dari panggilan http Angular 2 untuk mencegah kebocoran memori?
fetchFilm(index) {
var sub = this._http.get(`http://example.com`)
.map(result => result.json())
.map(json => {
dispatch(this.receiveFilm(json));
})
.subscribe(e=>sub.unsubscribe());
...
angular
memory-leaks
rxjs
angular2-http
born2net
sumber
sumber
Jawaban:
Jadi jawabannya tidak, Anda tidak.
Ng2
akan membersihkannya sendiri.Sumber layanan Http, dari sumber backend Http XHR Angular:
Perhatikan bagaimana menjalankannya
complete()
setelah mendapatkan hasilnya. Ini berarti sebenarnya berhenti berlangganan saat selesai. Jadi, Anda tidak perlu melakukannya sendiri.Berikut ini adalah tes untuk memvalidasi:
Seperti yang diharapkan, Anda dapat melihat bahwa itu selalu berhenti berlangganan secara otomatis setelah mendapatkan hasil dan selesai dengan operator yang dapat diamati. Ini terjadi pada batas waktu (# 3) sehingga kita dapat memeriksa status yang dapat diamati ketika semuanya selesai dan selesai.
Dan hasilnya
Jadi, tidak akan ada kebocoran karena
Ng2
berhenti berlangganan otomatis!Senang menyebutkan: Ini
Observable
dikategorikan sebagaifinite
, sebaliknyainfinite
Observable
yang merupakan aliran data tak terbatas dapat dipancarkan seperticlick
pendengar DOM misalnya.Terima kasih, @rubyboy atas bantuannya.
sumber
Apa yang kalian bicarakan !!!
OK jadi ada dua alasan untuk berhenti berlangganan dari yang bisa diamati. Sepertinya tidak ada yang berbicara banyak tentang alasan kedua yang sangat penting!
(Untuk HTTP ini sebenarnya juga akan membatalkan permintaan di browser - jadi tidak akan membuang waktu untuk membaca respons. Tapi itu sebenarnya merupakan tambahan untuk poin utama saya di bawah.)
Relevansi nomor 2 akan tergantung pada apa yang dilakukan oleh langganan Anda:
Pertimbangkan beberapa kasus:
1) Formulir login. Anda memasukkan nama pengguna dan kata sandi dan klik 'Login'. Bagaimana jika server lambat dan Anda memutuskan untuk menekan Escape untuk menutup dialog? Anda mungkin akan menganggap Anda tidak masuk, tetapi jika permintaan http kembali setelah Anda menekan escape maka Anda masih akan menjalankan logika apa pun yang Anda miliki di sana. Ini dapat mengakibatkan pengalihan ke halaman akun, cookie login yang tidak diinginkan atau variabel token yang ditetapkan. Ini mungkin bukan yang diharapkan pengguna Anda.
2) Formulir 'kirim email'.
Jika
subscribe
penangan untuk 'sendEmail' melakukan sesuatu seperti memicu animasi 'Email Anda terkirim', transfer Anda ke halaman lain atau mencoba mengakses apa pun yang telah dibuang Anda mungkin mendapatkan pengecualian atau perilaku yang tidak diinginkan.Hati-hati juga untuk tidak menganggap
unsubscribe()
berarti 'membatalkan'. Setelah pesan HTTP dalam penerbanganunsubscribe()
TIDAK akan membatalkan permintaan HTTP jika sudah mencapai server Anda. Itu hanya akan membatalkan respons yang kembali kepada Anda. Dan email itu mungkin akan dikirim.Jika Anda membuat langganan untuk mengirim email langsung ke dalam komponen UI maka Anda mungkin ingin berhenti berlangganan pada saat membuang, tetapi jika email tersebut dikirim oleh layanan terpusat non-UI maka Anda mungkin tidak perlu melakukannya.
3) Komponen sudut yang dihancurkan / ditutup. Setiap http yang dapat diamati masih berjalan pada saat itu akan menyelesaikan dan menjalankan logikanya kecuali Anda berhenti berlangganan
onDestroy()
. Apakah konsekuensinya sepele atau tidak akan tergantung pada apa yang Anda lakukan dalam pengendali berlangganan. Jika Anda mencoba memperbarui sesuatu yang tidak ada lagi Anda mungkin mendapatkan kesalahan.Kadang-kadang Anda mungkin memiliki beberapa tindakan yang Anda inginkan jika komponen dibuang, dan beberapa Anda tidak. Misalnya mungkin Anda memiliki suara 'swoosh' untuk email yang dikirim. Anda mungkin ingin ini dimainkan walaupun komponen sudah ditutup, tetapi jika Anda mencoba menjalankan animasi pada komponen itu akan gagal. Jika demikian, beberapa logika kondisional tambahan di dalam berlangganan akan menjadi solusinya - dan Anda TIDAK ingin berhenti berlangganan http yang dapat diamati.
Jadi dalam menjawab pertanyaan aktual, tidak, Anda tidak perlu melakukannya untuk menghindari kebocoran memori. Tetapi Anda perlu melakukannya (sering) untuk menghindari efek samping yang tidak diinginkan dipicu oleh menjalankan kode yang dapat membuang pengecualian atau merusak kondisi aplikasi Anda.
Tip:
Subscription
Berisiclosed
properti boolean yang mungkin berguna dalam kasus lanjut. Untuk HTTP ini akan ditetapkan ketika selesai. Dalam Angular mungkin berguna dalam beberapa situasi untuk mengatur_isDestroyed
propertingDestroy
yang dapat diperiksa olehsubscribe
pawang Anda .Tips 2: Jika menangani beberapa langganan Anda dapat membuat
new Subscription()
objek ad-hoc danadd(...)
langganan lainnya - jadi ketika Anda berhenti berlangganan dari yang utama, ia akan berhenti berlangganan semua langganan yang ditambahkan juga.sumber
Memanggil
unsubscribe
metode ini bukan untuk membatalkan permintaan HTTP yang sedang berlangsung karena metode ini memanggil yangabort
ada di objek XHR yang mendasarinya dan menghapus pendengar pada acara memuat dan kesalahan:Yang mengatakan,
unsubscribe
menghapus pendengar ... Jadi itu bisa menjadi ide yang bagus tapi saya tidak berpikir itu perlu untuk satu permintaan ;-)Semoga ini bisa membantu Anda, Thierry
sumber
y = x.subscribe((x)=>data = x);
kemudian pengguna mengubah input danx.subscribe((x)=>cachlist[n] = x); y.unsubscribe()
hei Anda menggunakan sumber daya server kami, saya menang dapat membuangmu ..... dan dalam skenario lain: panggil sajay.stop()
semuanyaBerhenti berlangganan adalah suatu KEHARUSAN jika Anda ingin perilaku deterministik pada semua kecepatan jaringan.
Bayangkan komponen A dirender dalam sebuah tab - Anda mengklik tombol untuk mengirim permintaan 'GET'. Dibutuhkan 200 ms untuk tanggapan untuk kembali. Jadi, Anda aman untuk menutup tab kapan saja mengetahui bahwa, mesin akan lebih cepat daripada Anda & respons http diproses dan selesai sebelum tab ditutup dan komponen A dihancurkan.
Bagaimana dengan jaringan yang sangat lambat? Anda mengklik tombol, permintaan 'MENDAPATKAN' membutuhkan waktu 10 detik untuk menerima jawabannya, tetapi dalam 5 detik menunggu Anda memutuskan untuk menutup tab. Itu akan menghancurkan komponen A menjadi sampah di lain waktu. Tunggu sebentar! , kami tidak berhenti berlangganan - sekarang 5 detik kemudian, respons muncul kembali dan logika dalam komponen yang hancur akan dieksekusi. Eksekusi itu sekarang dipertimbangkan
out-of-context
dan dapat menghasilkan banyak hal termasuk kinerja yang sangat rendah.Jadi, praktik terbaik adalah menggunakan
takeUntil()
dan berhenti berlangganan panggilan http saat komponen dihancurkan.sumber
BehaviorSubject()
bukannya dan menelepon hanyacomplete()
dingOnDestroy()
?BehaviourSubject
berbeda?Juga dengan modul HttpClient baru, perilaku tetap sama
sumber
Anda tidak boleh berhenti berlangganan dari observable yang selesai secara otomatis (mis. Http, panggilan). Tapi itu perlu untuk berhenti berlangganan seperti yang dapat diamati seperti
Observable.timer()
.sumber
Setelah beberapa saat pengujian, baca dokumentasi dan kode sumber HttpClient.
HttpClient:
https://github.com/angular/angular/blob/master/packages/common/http/src/client.tsHttpXhrBackend :
https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.tsHttpClientModule
: https://indepth.dev/exploring-the-httpclientmodule-in-angular/Universitas Angular: https://blog.angular-university.io/angular-http/
Dan jawaban untuk seluruh Masalah "apakah saya MEMBUTUHKAN" untuk berhenti berlangganan?
Tergantung. Http call Memoryleaks tidak menjadi masalah. Masalahnya adalah logika dalam fungsi panggilan balik Anda.
Misalnya: Routing atau Login.
Jika panggilan Anda adalah panggilan masuk, Anda tidak perlu "berhenti berlangganan" tetapi Anda harus memastikan jika Pengguna meninggalkan halaman, Anda menangani respons dengan benar tanpa adanya pengguna.
Dari menjengkelkan menjadi berbahaya
Sekarang bayangkan saja, jaringan lebih lambat dari biasanya, panggilan membutuhkan waktu lebih lama 5 detik, dan pengguna meninggalkan tampilan login dan pergi ke "tampilan dukungan".
Komponen mungkin tidak aktif tetapi berlangganan. Jika ada respons, pengguna akan tiba-tiba dialihkan (tergantung implementasi handleResponse () Anda).
Ini bukan baik.
Bayangkan saja pengguna meninggalkan pc, percaya dia belum login. Tapi Anda masuk log logis pengguna, sekarang Anda memiliki masalah keamanan.
Apa yang dapat Anda lakukan TANPA berhenti berlangganan?
Membuat panggilan Anda tergantung pada kondisi tampilan saat ini:
Pengguna
.pipe(takeWhile(value => this.isActive))
untuk memastikan respons hanya ditangani ketika tampilan aktif.Tetapi bagaimana Anda bisa yakin bahwa langganan tidak menyebabkan kebocoran memori?
Anda dapat login jika "teardownLogic" diterapkan.
The teardownLogic dari suatu langganan akan dipanggil ketika subkripsi kosong atau berhenti berlangganan.
Anda tidak harus berhenti berlangganan. Anda harus tahu jika ada masalah dalam logika Anda, yang dapat menyebabkan Masalah dalam langganan Anda. Dan urus mereka. Dalam kebanyakan kasus, itu tidak akan menjadi masalah, tetapi terutama pada tugas-tugas penting seperti autorisasi, Anda harus menjaga perilaku yang tidak terduga, apakah itu dengan "berhenti berlangganan" atau logika lain seperti pemipaan atau fungsi panggilan balik bersyarat.
mengapa tidak selalu berhenti berlangganan saja?
Bayangkan Anda membuat permintaan put atau postingan. Server menerima pesan dengan cara apa pun, hanya tanggapannya yang membutuhkan waktu. Berhenti berlangganan, tidak akan membatalkan pos atau menempatkan. Tetapi ketika Anda berhenti berlangganan, Anda tidak akan memiliki kesempatan untuk menangani respons atau menginformasikan Pengguna, misalnya melalui Dialog atau Toast / Pesan dll.
Wich menyebabkan Pengguna percaya, bahwa permintaan put / post tidak dilakukan.
Jadi itu tergantung. Ini adalah keputusan desain Anda, bagaimana menangani masalah seperti itu.
sumber
Anda pasti harus membaca artikel ini . Ini menunjukkan kepada Anda mengapa Anda harus selalu berhenti berlangganan bahkan dari http .
Memperbarui
Penegasan di atas tampaknya benar, tetapi bagaimanapun, ketika jawabannya kembali berlangganan http dihancurkan pula
sumber
RxJS diamati pada dasarnya terkait dan bekerja sesuai dengan yang Anda berlangganan. Ketika kita membuat observable dan gerakan kita menyelesaikannya, observable secara otomatis akan ditutup dan berhenti berlangganan.
Mereka bekerja dengan cara yang sama dari para pengamat tetapi urutannya sangat berbeda. Praktik yang lebih baik untuk berhenti berlangganan mereka ketika komponen semakin hancur. Kami kemudian bisa melakukannya dengan misalnya. ini. $ manageSubscription.unsubscibe ()
Jika kita telah membuat sintaks yang dapat diamati seperti yang disebutkan di bawah ini seperti
** mengembalikan yang baru Dapat Diobservasi ((pengamat) => {** // Itu membuat diamati dalam keadaan dingin ** observer.complete () **}) **
sumber