Pembangunan web moden sangat bergantung pada aktiviti tak segerak untuk membolehkan aplikasi responsif dan interaktif. Sama ada mengambil data daripada API, membaca fail atau menjalankan pemasa, proses ini mesti berjalan di latar belakang tanpa membekukan antara muka. JavaScript menawarkan anda cara yang boleh dipercayai untuk mengendalikan pekerjaan ini. Artikel ini merangkumi semua yang anda perlu tahu tentang janji, termasuk idea asas dan ciri lanjutan, untuk membangunkan atur cara tak segerak tanpa ralat.
Dalam artikel ini anda akan belajar tentang —
Apakah itu Janji?
Mengapa Gunakan Janji?
Bagaimana Janji Berfungsi?
Mengendalikan Janji
Merangkai Janji
Ralat Mengendalikan Janji
Ciri Janji Lanjutan
Aliran Pelaksanaan JavaScript dengan Janji (Penting)
Menukar Rantaian Janji kepada Async/Menunggu
Amalan Terbaik dan Kesilapan Biasa
Janji dalam JavaScript adalah sama dengan membuat "janji" untuk melakukan sesuatu pada masa hadapan. Apabila anda membuat janji, anda berkata, "Saya berjanji untuk memberikan anda hasilnya nanti." Hasil ini boleh menjadi kejayaan atau kegagalan.
Dalam erti kata lain, janji ialah objek yang menggambarkan kejayaan muktamad (atau kegagalan) operasi tak segerak dan nilai terhasilnya. Ia membolehkan anda mengaitkan pengendali dengan kejayaan atau kegagalan tindakan tak segerak, menjadikan kod anda lebih mudah dibaca dan diselenggara.
Dalam JavaScript, contohnya, operasi yang memakan masa seperti mendapatkan semula data daripada pelayan-biasanya dicapai dengan panggilan balik. Panggilan balik hanyalah fungsi yang dihantar ke fungsi lain untuk dilaksanakan selepas tugas selesai. Anda mungkin menggunakan panggilan balik, sebagai contoh, untuk memproses data apabila ia tiba dari pelayan.
Namun, apabila terdapat operasi yang kompleks, penggunaan panggil balik menjadi agak kemas. Kekacauan ini dikenali sebagai "neraka panggil balik", di mana seseorang boleh mempunyai panggilan balik dalam yang lain, dan ini menjadikan kod tidak boleh dibaca dan tidak terurus.
Contoh Neraka Panggilan Balik:
fetchData((data) => { processData(data, (processedData) => { saveData(processedData, (result) => { console.log(result); }); }); });
Seperti yang ditunjukkan di atas, kod tersebut menjadi semakin sukar untuk dibaca dan diselenggara dalam pangkalan kod yang lebih besar kerana strukturnya yang sangat bersarang, sering dirujuk sebagai "neraka panggilan balik".
Janji telah diperkenalkan untuk menangani masalah ini, menawarkan cara yang lebih bersih dan teratur untuk mengendalikan tugas tak segerak dengan membenarkan rantaian dengan cara yang lebih mudah dibaca.
fetchData((data) => { processData(data, (processedData) => { saveData(processedData, (result) => { console.log(result); }); }); });
Pendekatan ini meratakan struktur dan menjadikan kod lebih mudah dibaca dan diselenggara.
Janji dalam JavaScript boleh berada dalam salah satu daripada tiga keadaan:
Belum selesai: Ini adalah langkah awal. Janji masih belum ditunaikan.
Ditepati: Janji telah berjaya diselesaikan bermakna ia diselesaikan dan mempunyai nilai.
Ditolak: Janji tidak berjaya diselesaikan, dan ia membawa mesej ralat.
Sintaks Asas
fetchData() .then(processData) .then(saveData) .then(console.log) .catch(console.error);
Dalam contoh ini, janji diselesaikan selepas 1 saat dengan mesej "Janji diselesaikan!". Kaedah.then() digunakan untuk mengendalikan nilai yang diselesaikan.
Kaedah.then() digunakan untuk mengendalikan perkara yang berlaku apabila janji berjaya diselesaikan. Ia mendaftarkan fungsi (panggilan balik) untuk dijalankan apabila janji dipenuhi.
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Promise resolved!"); }, 1000); }); myPromise.then(result => console.log(result));
Kaedah.catch() digunakan untuk mengendalikan perkara yang berlaku apabila janji gagal. Ia mendaftarkan fungsi (panggilan balik) untuk dijalankan apabila janji ditolak.
myPromise.then(data => { console.log("Data received:", data); });
Kaedah.finally() membolehkan anda menjalankan beberapa kod selepas janji dilakukan, sama ada ia berjaya atau tidak.
myPromise.catch(error => { console.error("Error:", error); });
Perantaian membolehkan anda melaksanakan tugasan secara berurutan dengan melepasi keputusan yang sebelumnya. Kemudian teruskan ke seterusnya.then(). Ini membolehkan anda mengendalikan beberapa tugas tak segerak secara berurutan.
Contoh Rantaian:
myPromise.finally(() => { console.log("Cleanup tasks"); });
Contoh ini menggunakan each.then()untuk mengendalikan setiap langkah dalam proses, membolehkan aliran data yang jelas. Ini membolehkan anda melihat cara keputusan satu peringkat dipindahkan ke peringkat seterusnya.
Janji memudahkan pengendalian ralat dengan membenarkan mereka menurunkan rantaian kepada kaedah.catch() untuk penyelesaian. Ini menghapuskan keperluan untuk mengendalikan kegagalan pada setiap fasa, memastikan kod anda lebih jelas dan lebih mudah untuk diurus.
Contoh dengan Penyebaran Ralat:
fetch('https://api.example.com/user') .then(response => response.json()) .then(data => { console.log("Processed data:", data); return processData(data); }) .then(finalResult => { console.log("Final result:", finalResult); }) .catch(error => console.error("Error:", error));
Jika mana-mana langkah dalam rantai janji gagal, ralat akan ditangkap oleh blok.catch(). Ini memudahkan untuk menangani isu dan memastikan kod anda berjalan lancar.
Kaedah Promise.all() membolehkan anda menjalankan beberapa janji serentak dan menunggu semuanya selesai. Jika semua janji ditepati, anda akan menerima keputusan setiap satu. Jika mana-mana janji gagal, ia mengesan kesilapan itu.
fetchData() .then(processData) .then(saveData) .catch(error => console.error("An error occurred:", error));
Dalam contoh ini, jika mana-mana janji gagal, keseluruhan Promise.all() gagal.
Kaedah Promise.race() mengembalikan hasil janji pertama yang selesai, sama ada berjaya atau gagal.
fetchData((data) => { processData(data, (processedData) => { saveData(processedData, (result) => { console.log(result); }); }); });
Dalam contoh ini, mana-mana janji (fetchData1 atau fetchData2) yang dilengkapkan dahulu akan mempunyai hasilnya dilog masuk ke konsol.
Kaedah Promise.allSettled() menunggu semua janji yang anda berikan berada dalam keadaan berjaya atau gagal dan kemudian selesai. Tatasusunan kemudian dikembalikan yang mempunyai keputusan setiap janji.
fetchData() .then(processData) .then(saveData) .then(console.log) .catch(console.error);
Dalam contoh ini, Promise.allSettled() menunggu untuk kedua-dua fetchData1() dan fetchData2() selesai. Ia kemudian merekodkan status dan hasil (atau ralat) setiap janji. Dengan cara ini, anda boleh melihat apa yang berlaku dengan setiap janji, tidak kira sama ada ia berjaya atau gagal.
Kaedah Promise.any() menunggu janji pertama diselesaikan dengan betul daripada senarai janji. Sekiranya sekurang-kurangnya satu janji diselesaikan, nilai akan dikembalikan oleh kaedah Promise.any(). Jika semua janji ditolak, kaedah ini akan menimbulkan ralat.
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Promise resolved!"); }, 1000); }); myPromise.then(result => console.log(result));
Dalam contoh ini, Promise.any() menunggu janji pertama berjaya diselesaikan. Prosedur mengembalikan hasil janji pertama yang berjaya, dalam kes ini promise2dengan nilai 'Kejayaan A'. Jika semua janji ditolak, blok.catch() dilaksanakan, mengelog mesej ralat. Strategi ini bermanfaat apabila anda ingin menerima hasil janji pertama yang berjaya tanpa perlu menunggu selebihnya.
Berikut ialah contoh untuk menggambarkan ini:
myPromise.then(data => { console.log("Data received:", data); });
Dalam contoh ini:
console.log(2) berjalan dahulu kerana ia adalah operasi segerak biasa.
console.log (6) berjalan seterusnya kerana ia juga segerak.
The promise’s.then()berjalan sebelum panggilan balik setTimeout kerana promise ialah microtasks, yang mempunyai keutamaan yang lebih tinggi, justeru mencetak 3.
Akhir sekali, panggilan balik setTimeout berjalan, kerana ia adalah tugasan makro dan mencetak 4.
Jadi sentiasa ingat, promise’s.then()dilaksanakan sebelum panggilan balik setTimeout disebabkan keutamaan baris gilir microtask.
Dalam JavaScript, kod berjalan dalam susunan tertentu: pertama kod segerak, kemudian microtasks (seperti promises), dan akhirnya, macrotasks (likesetTimeout).
Berikut ialah satu contoh untuk menerangkan perkara ini:
fetchData((data) => { processData(data, (processedData) => { saveData(processedData, (result) => { console.log(result); }); }); });
Dalam contoh ini, kod segerak dijalankan dahulu, pengelogan 3, 6, 2, 7 dan 8. Setelah kod segerak selesai, microtasks (the.then() callbacks) diproses, log 1 dan 9. Akhir sekali, macrotasks (dari setTimeout) laksanakan mengikut urutan kelewatan mereka, log 21 (0ms) dan 13 (10ms). Ini menyerlahkan perintah pelaksanaan JavaScript: kod segerak > microtasks > tugasan makro.
Apabila anda membuat janji, panggilan pertama untuk menyelesaikan atau menolak adalah satu-satunya yang penting. Semua panggilan lain ditolak.
Berikut ialah contoh untuk menggambarkan ini:
fetchData() .then(processData) .then(saveData) .then(console.log) .catch(console.error);
Dalam contoh ini, janji diselesaikan dengan nilai 1. Azam kedua dan panggilan tolak diabaikan kerana janji telah pun diselesaikan dengan azam pertama.
Apabila anda berjanji, each.then() mengendalikan satu langkah dalam proses itu.
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Promise resolved!"); }, 1000); }); myPromise.then(result => console.log(result));
Dalam contoh ini, Promise.resolve(1) bermula dengan nilai 1, tetapi yang pertama .then(() => 2) mengembalikan 2. .then(3) seterusnya diabaikan dan nilai 2 diteruskan. Nilai .then((value) => * 3) mendarabkan nilai dengan 3, menghasilkan 6. The .then(Promise.resolve(4)) tidak mengubah nilai dan akhirnya, .then(console. log) log 6. Ini menunjukkan cara nilai dihantar melalui rantai, dengan nilai bukan fungsi diabaikan.
myPromise.then(data => { console.log("Data received:", data); });
Dalam contoh ini, kami merantai kaedah berbilang.then(),.catch(), dan.finally() untuk menunjukkan cara pelbagai peringkat penyelesaian janji dikendalikan. Jom pecahkan:
akhirnya() tidak menerima hujah:
Blok finally() melaksanakan kod pembersihan tetapi tidak mengambil atau lulus sebarang nilai. Ia digunakan untuk memastikan kod tertentu berjalan tanpa mengira hasil janji.
Mengembalikan nilai dalam finally() tidak menjejaskan janji:
Jika anda mengembalikan nilai dalam blok finally(), ia tidak menjejaskan rantai janji atau nilai akhir. Ia dilaksanakan selepas resolusi janji/penolakan tetapi tidak mengubah keputusannya.
Melempar ralat ke dalam finally() menyebabkan penolakan:
Jika anda membuang ralat atau mengembalikan janji yang ditolak dalam finally(), ia akan menyebabkan rantai janji menolak dengan sebab ralat atau penolakan.
myPromise.catch(error => { console.error("Error:", error); });
ATAU
myPromise.finally(() => { console.log("Cleanup tasks"); });
Contoh:
fetchData((data) => { processData(data, (processedData) => { saveData(processedData, (result) => { console.log(result); }); }); });
Async/wait ialah kaedah untuk menggunakan janji yang menyebabkan kod menjadi lebih seperti kod yang ditulis dalam mod segerak. Istilah yang sering digunakan ialah "gula sintaksis" kerana ia memberikan laluan yang lebih mudah dan bersih untuk melakukan kod tak segerak.
fetchData() .then(processData) .then(saveData) .then(console.log) .catch(console.error);
Anda boleh menggabungkan janji dengan async/menunggu untuk pelaksanaan selari menggunakan Promise.all().
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Promise resolved!"); }, 1000); }); myPromise.then(result => console.log(result));
Elakkan Bersarang Dalam: Gunakan rantaian atau async/tunggu untuk memastikan kod rata dan boleh dibaca.
Sentiasa Tangani Ralat: Pastikan setiap rantai janji mempunyai a.catch() atau try/catch block.
Gunakan Perlaksanaan Selari dengan Bijak: Hanya gunakan Promise.all() apabila tugasan adalah bebas tetapi perlu diselesaikan bersama.
Janji JavaScript ialah salah satu cara terbaik untuk menangani operasi anda yang memakan masa, seperti, mendapatkan semula data pada pelayan. Ia juga membantu anda menulis kod yang lebih bersih dan lebih mudah diselenggara, dan amalan perkara yang telah anda pelajari akan melengkapkan anda untuk memanfaatkan sepenuhnya pengekodan tak segerak. Sebaik sahaja anda mendapat pengalaman praktikal dan mula mengendalikan ralat secara elegan, janji akan menjadi sebahagian besar JavaScript.
Terima kasih kerana membaca! Jika anda mendapati artikel ini membantu, sila serlahkan, tepuk tangan, tinggalkan ulasan atau hubungi saya di Twitter/X dan LinkedIn kerana ia amat dihargai dan membantu memastikan kandungan seperti ini percuma!
Atas ialah kandungan terperinci Semua yang Anda Perlu Tahu Tentang Janji JavaScript dan Cara Ia Berfungsi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!