cari
Rumahhujung hadapan webtutorial cssDikatakan dengan pasti menghantar permintaan HTTP sebagai pengguna meninggalkan halaman

Dikatakan dengan pasti menghantar permintaan HTTP sebagai pengguna meninggalkan halaman

Dalam banyak kes, saya perlu menghantar permintaan HTTP yang mengandungi beberapa data untuk merekodkan apa yang pengguna lakukan, seperti menavigasi ke halaman lain atau mengemukakan borang. Pertimbangkan contoh ini, yang menghantar beberapa maklumat ke perkhidmatan luaran semasa mengklik pautan:

 <a href="https://www.php.cn/link/3cbfb2330b21840b385a45c958602663">Pergi ke halaman</a>

document.getElementById ('link'). AddEventListener ('klik', (e) => {
  Ambil ("/log", {
    Kaedah: "pos",
    tajuk: {
      "Kandungan-jenis": "Aplikasi/JSON"
    }, 
    badan: json.stringify ({
      Ada: "Data"
    })
  });
});

Tidak ada yang sangat rumit di sini. Pautan berfungsi seperti biasa (saya tidak menggunakan e.preventDefault() ), tetapi sebelum tingkah laku itu berlaku, permintaan pos dicetuskan. Tidak perlu menunggu sebarang respons. Saya hanya mahu menghantarnya ke mana -mana perkhidmatan yang saya lawati.

Pada pandangan pertama, anda mungkin berfikir bahawa penjadualan permintaan disegerakkan, selepas itu kami akan terus menavigasi dari halaman, dan pelayan lain berjaya memproses permintaan tersebut. Tetapi ternyata ini tidak selalu berlaku.

Penyemak imbas tidak menjamin bahawa permintaan HTTP terbuka akan dikekalkan

Apabila peristiwa -peristiwa tertentu berlaku untuk menamatkan halaman dalam penyemak imbas, tidak ada jaminan bahawa permintaan HTTP yang diproses akan berjaya (lebih lanjut mengenai kitaran hayat halaman "penamatan" dan negeri -negeri lain). Kebolehpercayaan permintaan ini mungkin bergantung kepada beberapa faktor -sambungan rangkaian, prestasi aplikasi, dan juga konfigurasi perkhidmatan luaran itu sendiri.

Oleh itu, menghantar data pada momen-momen ini boleh jauh dari yang boleh dipercayai, dan jika anda bergantung pada log ini untuk membuat keputusan perniagaan sensitif data, mungkin ada masalah yang berpotensi penting.

Untuk menggambarkan ketidakpercayaan ini, saya menyediakan aplikasi ekspres kecil dengan halaman menggunakan kod di atas. Apabila pautan diklik, penyemak imbas menavigasi ke /other , tetapi sebelum ini berlaku, permintaan pos dikeluarkan.

Walaupun segala -galanya berlaku, saya membuka tab "Rangkaian" penyemak imbas saya dan menggunakan kelajuan sambungan "Slow 3G". Selepas halaman dimuat, saya membersihkan kayu balak dan semuanya kelihatan tenang:

Tetapi apabila anda mengklik pada pautan, perkara menjadi salah. Apabila navigasi berlaku, permintaan dibatalkan.

Ini meninggalkan kita hampir tidak dapat memastikan bahawa perkhidmatan luaran sebenarnya boleh mengendalikan permintaan. Untuk mengesahkan tingkah laku ini, ini juga berlaku apabila kita menggunakan window.location untuk menavigasi secara programatik:

 document.getElementById ('link'). AddEventListener ('klik', (e) => {
  E.PreventDefault ();

  // Permintaan itu telah beratur tetapi dibatalkan sejurus selepas navigasi berlaku.
  Ambil ("/log", {
    Kaedah: "pos",
    tajuk: {
      "Kandungan-jenis": "Aplikasi/JSON"
    },
    badan: json.stringify ({
      Beberapa: 'Data'
    }),
  });

  window.location = e.target.href;
});

Permintaan yang belum selesai ini boleh ditinggalkan tanpa mengira bagaimana atau apabila navigasi berlaku dan apabila halaman aktif berakhir.

Mengapa ia dibatalkan?

Penyebab utama masalah ialah secara lalai, permintaan XHR (melalui fetch atau XMLHttpRequest ) adalah tak segerak dan tidak menyekat. Sebaik sahaja permintaan itu beratur, kerja sebenar permintaan itu dihantar ke API peringkat pelayar di latar belakang.

Ini hebat dari segi prestasi - anda tidak mahu permintaan itu mengambil benang utama. Tetapi ini juga bermakna bahawa apabila halaman memasuki keadaan "penamatan", mereka berisiko ditinggalkan dan tidak ada jaminan bahawa kerja latar belakang dapat diselesaikan. Inilah ringkasan Google mengenai keadaan kitaran hayat tertentu:

Sebaik sahaja halaman mula menyahpasang dan dibersihkan dari ingatan oleh penyemak imbas, ia berada dalam keadaan yang ditamatkan. Di negeri ini, tiada tugas baru tidak dapat dimulakan dan boleh ditamatkan jika tugas yang sedang berjalan berjalan terlalu lama.

Singkatnya, andaian reka bentuk penyemak imbas adalah bahawa apabila halaman ditutup, tidak perlu terus memproses sebarang proses latar belakang yang beratur.

Jadi, apakah pilihan kita?

Cara yang paling jelas untuk mengelakkan masalah ini adalah untuk melambatkan tindakan pengguna sebanyak mungkin sehingga permintaan itu mengembalikan respons. Pada masa lalu, ini dilakukan dengan salah dengan menggunakan bendera penyegerakan yang disokong dalam XMLHttpRequest . Tetapi dengan menggunakannya sepenuhnya menghalang benang utama, menyebabkan banyak masalah prestasi - saya telah menulis beberapa perkara mengenai perkara ini pada masa lalu - jadi idea ini tidak boleh dipertimbangkan. Malah, ia akan keluar dari platform (Chrome V80 telah mengeluarkannya).

Sebaliknya, jika anda akan mengambil pendekatan ini, lebih baik menunggu janji untuk menyelesaikan respons yang dikembalikan. Sebaik sahaja anda kembali, anda boleh melakukan tingkah laku dengan selamat. Menggunakan coretan kod sebelumnya kami, ini mungkin kelihatan seperti ini:

 document.getElementById ('link'). AddEventListener ('klik', async (e) => {
  E.PreventDefault ();

  // tunggu jawapan untuk kembali ...
  Tunggu ambil ("/log", {
    Kaedah: "pos",
    tajuk: {
      "Kandungan-jenis": "Aplikasi/JSON"
    },
    badan: json.stringify ({
      Beberapa: 'Data'
    }),
  });

  // ... dan kemudian menavigasi untuk pergi.
  window.location = e.target.href;
});

Ini boleh melakukan pekerjaan itu, tetapi mempunyai beberapa kelemahan yang tidak remeh.

Pertama, ia memberi kesan kepada pengalaman pengguna dengan melambatkan berlakunya tingkah laku yang diperlukan. Mengumpul data analisis pasti memberi manfaat kepada perniagaan (dan kepada pengguna masa depan), tetapi itu jauh dari ideal kerana ia membuat pengguna semasa membayar untuk mencapai manfaat ini. Belum lagi, sebagai kebergantungan luaran, sebarang latensi atau isu prestasi lain dalam perkhidmatan itu sendiri akan dapat dilihat kepada pengguna. Sekiranya masa tamat dari perkhidmatan analisis anda menyebabkan pelanggan gagal menyelesaikan operasi bernilai tinggi, semua orang akan kalah.

Kedua, pendekatan ini tidak boleh dipercayai kerana pada mulanya bunyi, kerana beberapa tingkah laku penamatan tidak dapat ditangguhkan secara programatik. Sebagai contoh, e.preventDefault() tidak berguna dalam melambatkan pengguna untuk menutup tab penyemak imbas. Jadi, paling baik, ia hanya akan merangkumi pengumpulan data dari tindakan pengguna tertentu , tetapi tidak cukup untuk mempercayainya sepenuhnya.

Arahkan penyemak imbas untuk mengekalkan permintaan yang belum selesai

Syukurlah, kebanyakan pelayar mempunyai pilihan terbina dalam untuk mengekalkan permintaan HTTP yang belum selesai tanpa menjejaskan pengalaman pengguna.

Gunakan logo Keepalive Fetch

Jika bendera keepalive ditetapkan kepada true apabila menggunakan fetch() , permintaan yang sepadan masih terbuka walaupun halaman yang memulakan permintaan telah ditamatkan. Menggunakan contoh awal kami, ini akan menjadikan pelaksanaannya kelihatan seperti ini:

 <a href="https://www.php.cn/link/3cbfb2330b21840b385a45c958602663">Pergi ke halaman</a>

document.getElementById ('link'). AddEventListener ('klik', (e) => {
  Ambil ("/log", {
    Kaedah: "pos",
    tajuk: {
      "Kandungan-jenis": "Aplikasi/JSON"
    },
    badan: json.stringify ({
      Ada: "Data"
    }),
    Keepalive: Benar
  });
});

Semasa mengklik pada pautan dan navigasi halaman berlaku, tiada pembatalan permintaan berlaku:

Sebaliknya, kita mendapat keadaan (tidak diketahui) semata -mata kerana halaman aktif tidak pernah menunggu sebarang respons yang diterima.

Kod satu baris sedemikian mudah untuk diperbaiki, terutamanya jika ia adalah sebahagian daripada API penyemak imbas biasa. Walau bagaimanapun, jika anda mencari pilihan yang lebih berpusat dengan antara muka yang lebih mudah, ada cara lain untuk melakukannya dengan sokongan penyemak imbas yang sama.

Gunakan Navigator.SendBeacon ()

Fungsi Navigator.sendBeacon() digunakan secara khusus untuk menghantar permintaan sehala (suar). Pelaksanaan asas adalah seperti berikut, yang menghantar jawatan dengan JSON yang berlapis dan Content-Type "teks/biasa":

 Navigator.SendBeacon ('/log', json.stringify ({
  Ada: "Data"
}));

Tetapi API ini tidak membenarkan anda menghantar tajuk tersuai. Oleh itu, untuk menghantar data kami sebagai "Aplikasi/JSON", kita perlu membuat tweak kecil dan menggunakan gumpalan:

 <a href="https://www.php.cn/link/3cbfb2330b21840b385a45c958602663">Pergi ke halaman</a>

document.getElementById ('link'). AddEventListener ('klik', (e) => {
  const blob = blob baru ([json.stringify ({some: "data"})], {type: 'application/json; charset = utf-8'});
  Navigator.SendBeacon ('/log', gumpalan);
});

Pada akhirnya, kami mendapat hasil yang sama - permintaan itu selesai walaupun selepas halaman dilayari. Tetapi ada beberapa perkara yang berlaku, yang mungkin menjadikannya lebih baik daripada fetch() : suar dihantar pada keutamaan yang rendah.

Untuk demonstrasi, inilah yang dipaparkan dalam tab Rangkaian apabila menggunakan kedua -dua fetch() dan sendBeacon() dengan keepalive :

Secara lalai, fetch() mendapat keutamaan "tinggi", manakala suar (dinyatakan sebagai "ping" jenis di atas) mempunyai keutamaan "terendah". Ini adalah perkara yang baik untuk permintaan yang tidak penting untuk fungsi halaman. Terus dari spesifikasi Beacon:

Spesifikasi ini mentakrifkan antara muka yang [...] meminimumkan persaingan sumber dengan operasi masa kritikal yang lain sambil memastikan bahawa permintaan tersebut masih diproses dan dihantar ke destinasi.

Dalam erti kata lain, sendBeacon() memastikan bahawa permintaannya tidak menghalang permintaan yang sangat penting untuk aplikasi dan pengalaman pengguna anda.

Sebutan kehormat atribut Ping

Perlu dinyatakan bahawa semakin banyak penyemak imbas menyokong atribut ping . Apabila dilampirkan pada pautan, ia mengeluarkan permintaan pos kecil:

<a href="https://www.php.cn/link/fef56cae0dfbabedeadb64bf881ab64f" ping="http://localhost:3000/log">
  Pergi ke halaman lain
</a>

Tajuk permintaan ini akan mengandungi halaman di mana pautan diklik (ping-dari), dan nilai HREF pautan (ping-to):

 <code>headers: { 'ping-from': 'http://localhost:3000/', 'ping-to': 'https://www.php.cn/link/fef56cae0dfbabedeadb64bf881ab64f' 'content-type': 'text/ping' // ...其他标头},</code>

Ia secara teknikal sama dengan menghantar suar, tetapi mempunyai beberapa batasan yang ketara:

  1. Ia adalah terhad untuk digunakan untuk pautan, yang akan menjadi pilihan yang buruk jika anda perlu menjejaki data yang berkaitan dengan interaksi lain seperti klik butang atau borang penyerahan.
  2. Pelayar menyokong dengan baik, tetapi tidak hebat. Pada masa penulisan, Firefox secara khusus tidak membolehkannya secara lalai.
  3. Anda tidak boleh menghantar data tersuai dengan permintaan. Seperti yang dinyatakan sebelum ini, anda hanya boleh mendapatkan beberapa tajuk ping-* paling banyak, dan mana-mana tajuk lain.

Semua dalam semua, ping adalah alat yang hebat jika anda hanya menghantar permintaan mudah dan tidak mahu menulis mana -mana JavaScript tersuai. Walau bagaimanapun, jika anda perlu menghantar lebih banyak kandungan, ia mungkin bukan pilihan terbaik.

Jadi, mana yang harus saya pilih?

Sudah tentu ada perdagangan ketika menghantar permintaan terakhir kedua menggunakan fetch() atau sendBeacon() dengan keepalive . Untuk membantu memberitahu pendekatan mana yang terbaik untuk situasi yang berbeza, berikut adalah beberapa perkara yang perlu dipertimbangkan:

Anda mungkin memilih mengambil () KeepAlive dalam kes -kes berikut:

  • Anda perlu lulus tajuk tersuai dengan mudah menggunakan permintaan.
  • Anda ingin mengeluarkan permintaan mendapatkan perkhidmatan, bukan permintaan pos.
  • Anda menyokong penyemak imbas yang lebih tua (seperti IE) dan telah mengambil polyfill yang dimuatkan.

Walau bagaimanapun, SendBeacon () mungkin menjadi pilihan yang lebih baik dalam kes -kes berikut:

  • Anda membuat permintaan perkhidmatan mudah yang tidak memerlukan banyak penyesuaian.
  • Anda lebih suka API yang lebih ringkas dan elegan.
  • Anda ingin memastikan bahawa permintaan anda tidak bersaing dengan permintaan keutamaan yang lain yang dihantar dalam permohonan.

Elakkan mengulangi kesilapan yang sama

Terdapat sebab mengapa saya memilih untuk menggali jauh ke dalam cara penyemak imbas mengendalikan permintaan dalam proses apabila halaman berakhir. Tidak lama dahulu, selepas kami memulakan permintaan menembak dengan segera apabila kami menyerahkan borang itu, pasukan kami mendapati bahawa kekerapan jenis log analisis tertentu tiba -tiba berubah. Perubahan ini tiba -tiba dan signifikan - kira -kira 30% daripada apa yang kita lihat dalam sejarah.

Menggali punca masalah ini dan alat yang ada untuk mengelakkan daripada muncul semula masalah yang disimpan pada hari itu. Jadi jika ada, saya berharap dapat memahami nuansa cabaran -cabaran ini dapat membantu seseorang mengelakkan kesakitan yang kita hadapi. Rekod gembira!

Atas ialah kandungan terperinci Dikatakan dengan pasti menghantar permintaan HTTP sebagai pengguna meninggalkan halaman. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Apakah grid CSS?Apakah grid CSS?Apr 30, 2025 pm 03:21 PM

CSS Grid adalah alat yang berkuasa untuk mewujudkan susun atur web yang rumit dan responsif. Ia memudahkan reka bentuk, meningkatkan kebolehcapaian, dan menawarkan lebih banyak kawalan daripada kaedah yang lebih lama.

Apakah CSS Flexbox?Apakah CSS Flexbox?Apr 30, 2025 pm 03:20 PM

Artikel membincangkan CSS Flexbox, kaedah susun atur untuk penjajaran yang cekap dan pengedaran ruang dalam reka bentuk responsif. Ia menerangkan penggunaan Flexbox, membandingkannya dengan grid CSS, dan butiran sokongan penyemak imbas.

Bagaimanakah kita boleh membuat laman web kami responsif menggunakan CSS?Bagaimanakah kita boleh membuat laman web kami responsif menggunakan CSS?Apr 30, 2025 pm 03:19 PM

Artikel ini membincangkan teknik untuk membuat laman web responsif menggunakan CSS, termasuk tag Meta Viewport, grid fleksibel, media cecair, pertanyaan media, dan unit relatif. Ia juga meliputi menggunakan grid CSS dan Flexbox bersama -sama dan mengesyorkan rangka kerja CSS

Apakah harta saiz kotak CSS?Apakah harta saiz kotak CSS?Apr 30, 2025 pm 03:18 PM

Artikel ini membincangkan harta saiz kotak CSS, yang mengawal bagaimana dimensi elemen dikira. Ia menerangkan nilai seperti kotak kandungan, kotak sempadan, dan kotak padding, dan kesannya terhadap reka bentuk susun atur dan penjajaran bentuk.

Bagaimanakah kita boleh menghidupkan CSS?Bagaimanakah kita boleh menghidupkan CSS?Apr 30, 2025 pm 03:17 PM

Artikel membincangkan membuat animasi menggunakan CSS, sifat utama, dan menggabungkan dengan JavaScript. Isu utama adalah keserasian penyemak imbas.

Bolehkah kita menambah transformasi 3D ke projek kami menggunakan CSS?Bolehkah kita menambah transformasi 3D ke projek kami menggunakan CSS?Apr 30, 2025 pm 03:16 PM

Artikel membincangkan menggunakan CSS untuk transformasi 3D, sifat utama, keserasian penyemak imbas, dan pertimbangan prestasi untuk projek web. (Kira -kira aksara: 159)

Bagaimana kita boleh menambah kecerunan dalam CSS?Bagaimana kita boleh menambah kecerunan dalam CSS?Apr 30, 2025 pm 03:15 PM

Artikel ini membincangkan menggunakan kecerunan CSS (linear, radial, mengulangi) untuk meningkatkan visual laman web, menambah kedalaman, fokus, dan estetika moden.

Apakah unsur-unsur pseudo dalam CSS?Apakah unsur-unsur pseudo dalam CSS?Apr 30, 2025 pm 03:14 PM

Artikel membincangkan unsur-unsur pseudo dalam CSS, penggunaannya dalam meningkatkan gaya HTML, dan perbezaan dari kelas pseudo. Menyediakan contoh praktikal.

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini

Pelayar Peperiksaan Selamat

Pelayar Peperiksaan Selamat

Pelayar Peperiksaan Selamat ialah persekitaran pelayar selamat untuk mengambil peperiksaan dalam talian dengan selamat. Perisian ini menukar mana-mana komputer menjadi stesen kerja yang selamat. Ia mengawal akses kepada mana-mana utiliti dan menghalang pelajar daripada menggunakan sumber yang tidak dibenarkan.

SublimeText3 Linux versi baharu

SublimeText3 Linux versi baharu

SublimeText3 Linux versi terkini

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

PhpStorm versi Mac

PhpStorm versi Mac

Alat pembangunan bersepadu PHP profesional terkini (2018.2.1).