Tutorial JavaScript Moden: Janji, async/menunggu dan API

Kemaskini terakhir: 04/12/2025
Pengarang Ishak
  • Async/wait bergantung pada janji untuk menawarkan lebih banyak kod asynchronous yang boleh dibaca, lebih dekat dengan gaya segerak tradisional.
  • Fungsi Async sentiasa mengembalikan janji dan membolehkan anda menggunakan await untuk menjeda pelaksanaannya tanpa menyekat utas utama.
  • Ralat pengendalian dengan try/catch dan utiliti seperti Promise.all memudahkan untuk mengawal kegagalan dan menggabungkan beberapa operasi secara selari.
  • Penggunaan gabungan janji, async/menunggu dan API seperti fetch adalah asas pembangunan JavaScript berorientasikan rangkaian moden.

js

La pengaturcaraan tak segerak dalam JavaScript telah menjadi sangat diperlukan dalam pembangunan web moden: permintaan API, akses kepada pangkalan dataPembacaan fail atau sebarang operasi yang mengambil masa lebih daripada seketika bergantung padanya untuk memastikan antara muka berjalan lancar. Terima kasih kepada janji, async/menunggu dan API Kami mempunyai set alat yang sangat berkuasa untuk mengawal aliran itu tanpa menyekat aplikasi.

Selama bertahun-tahun corak itu digunakan terutamanya panggilan balik dan janji berantaiyang, walaupun berfungsi dengan baik, boleh berakhir dengan "neraka panggilan balik" yang terkenal atau dalam rantaian yang tidak berkesudahan. .then() y .catch() sukar untuk diikuti. Dengan kedatangan async/menunggu dalam ECMAScript 2017JavaScript mengambil lonjakan besar dalam kebolehbacaan, membenarkan kod tak segerak ditulis dalam gaya yang hampir sama dengan kod segerak tradisional.

Apakah pengaturcaraan tak segerak dalam JavaScript dan mengapa ia begitu penting?

La pengaturcaraan tak segerak Ia adalah satu cara untuk mengatur kod supaya tugas boleh dimulakan dan program boleh terus melaksanakan perkara lain tanpa "membeku" menunggu jawapan. Dalam JavaScript, ini penting kerana bahasa berjalan, dalam penyemak imbas dan dalam Node.js, pada a benang utama tunggal yang menangani kedua-dua logik dan antara muka.

Apabila anda membuang a Permintaan HTTP kepada APIApabila anda membaca fail atau menanyakan pangkalan data, operasi ini boleh mengambil masa dari milisaat hingga beberapa saat. Jika ia adalah segerak, pengguna akan melihat halaman dikunci dan tidak dapat berinteraksi. Dengan model tak segerak, enjin JavaScript mewakilkan tugas-tugas ini dan boleh terus bekerja dalam masa yang sama. mengecat UI, mengendalikan acara dan menjalankan skrip lain.

Pada asalnya, mekanisme standard untuk bertindak balas apabila operasi tamat adalah untuk lulus a fungsi panggil balik sebagai hujah. Fungsi itu telah dilaksanakan kemudian dengan hasil atau ralat. Masalahnya ialah, dengan merantai panggilan balik dalam panggilan balik lain, yang digeruni panggilan balik neraka: kod dengan terlalu banyak lekukan, sukar dibaca, nyahpepijat dan diselenggara.

Untuk menyelesaikan beberapa kekacauan itu, perkara berikut muncul: menjanjikanyang merangkum hasil operasi tak segerak dan membenarkan tindakan dirantai bersama dengan .then() dan menguruskan kegagalan dengan .catch()Ini sudah menjadi peningkatan yang hebat, tetapi ia masih meninggalkan kod yang penuh dengan panggilan balik "bersama" di sebalik kaedah tersebut.

Janji: asas async/menunggu

Sebelum memahami async/menunggu, adalah penting untuk menjadi sangat jelas tentang perkara a janji dalam JavaScriptJanji ialah objek yang mewakili hasil masa depan operasi tak segerak: sesuatu yang belum berlaku tetapi akan berlaku kemudian, sama ada berjaya atau tidak berjaya.

yang janji standard boleh didapati dalam salah satu daripada tiga keadaan yang jelas: belum selesai (menunggu) semasa operasi sedang dijalankan, selesai (dipenuhi) apabila ia berakhir dengan baik dan menghasilkan nilai, atau ditolak (ditolak) apabila ia gagal dan menghasilkan ralat. Itu keadaan janji menentukan panggilan balik yang akan dilaksanakan seterusnya.

Apabila anda membuat janji menggunakan pembina PromiseAnda memberikannya fungsi boleh laku yang menerima dua argumen: resolve y rejectJika operasi berjalan lancar, anda hubungi resolve(valor)Jika masalah berlaku, anda memohon reject(error)Kemudian, dari luar, anda boleh menggunakan miPromesa.then() untuk memproses keputusan dan .catch() untuk menguruskan ralat.

Selain janji buatan tangan, sudah banyak API bahasa moden Mereka memenuhi janji siri.. Fungsi fetch()Sebagai contoh, ia memulakan permintaan HTTP dan segera mengembalikan janji yang akhirnya akan diselesaikan dengan objek. Response atau ditolak jika terdapat kegagalan rangkaian.

Untuk bekerja dengan pelbagai tugas secara selari, JavaScript menawarkan utiliti seperti Promise.all()Kaedah ini mengambil pelbagai janji dan mengembalikan janji baharu yang diselesaikan hanya apabila semua janji berjaya diselesaikan, atau ditolak jika mana-mana janji gagal. Ini amat berguna apabila anda mahu menggabungkan data daripada sumber yang berbeza sebelum lebih jauh.

  Bagaimana untuk menghalang Outlook daripada memuat turun imej luaran secara automatik

Konsep utama: async, menunggu dan model ralat

Sintaks daripada async/await dibina berdasarkan janjiIa tidak menggantikan mereka. Apa yang dilakukannya ialah menyediakan cara yang lebih mudah, lebih jelas, lebih dekat dengan pengaturcaraan segerak, untuk bekerja dengan mereka, mengurangkan bunyi visual .then() dirantai.

Kata kuncinya async Ia diletakkan sebelum fungsi untuk memberitahu enjin JavaScript bahawa fungsi itu akan berfungsi secara tidak segerak dan, apa sahaja yang berlaku di dalam, akan sentiasa menepati janjiWalaupun anda mengembalikan nilai normal, enjin akan membalutnya secara automatik Promise.resolve(valor).

Bagi pihaknya, perkataan terpelihara await hanya boleh digunakan dalam fungsi yang diisytiharkan sebagai asyncFungsinya adalah untuk menjeda pelaksanaan dalam fungsi itu sehingga janji yang diberikan kepadanya dipenuhi. diselesaikan atau ditolak, secara langsung mengembalikan nilai yang diselesaikan atau membuang pengecualian jika janji berakhir dengan ralat.

apabila anda menggunakan await promesa dan janji itu diselesaikan, anda mendapat keputusan seolah-olah ia adalah panggilan segerak. Jika sebaliknya janji itu ditolak, Pengecualian dijana pada ketika itu., bersamaan dengan melakukan a throw errorIni membenarkan penggunaan semula struktur pengendalian ralat yang sama seperti dalam kod segerak, seperti try..catch.

Dengan membungkus panggilan tak segerak kami dalam satu blok try { ... } catch (error) { ... }Kami boleh menangkap kes di mana mana-mana janji gagal, memaparkan mesej yang sesuai kepada pengguna, atau membuat keputusan seperti mencuba semula, mengubah hala atau mengelog kegagalan ke sistem luaran.

Kata kunci async: fungsi yang sentiasa mengembalikan janji

Tempat async di hadapan sesuatu majlis Ini mempunyai dua akibat yang sangat penting: di satu pihak, ia memaksa nilai pulangan untuk sentiasa menjadi janji; sebaliknya, ia membolehkan penggunaan await dalam badan fungsi itu, yang mengubah sepenuhnya cara aliran tak segerak distrukturkan.

Jika anda mengisytiharkan sesuatu seperti async function sumar() { return 1; }Walaupun ia mungkin kelihatan seperti fungsi biasa, perkara yang anda perolehi sebenarnya ialah a fungsi yang mengembalikan janji yang telah diselesaikan sebelum ini dengan keberanian 1Di luar sistem anda, anda perlu mengakses hasil tersebut menggunakan await sumar() dengan sumar().then() jika anda lebih suka gaya berantai.

Anda juga boleh secara eksplisit mengembalikan janji daripada fungsi. async, sebagai contoh return Promise.resolve(1);dan tingkah laku akan sama. Dalam kedua-dua kes, fungsi itu diselaraskan dengan model janji, yang memudahkan gabungannya dengan fungsi tak segerak dan utiliti lain seperti Promise.all().

Ia adalah perkara biasa bahawa, apabila kita bermula, kita terlupa untuk menandakan fungsi seperti itu async namun kami menggunakan await dalamDalam keadaan itu, JavaScript akan membuang ralat sintaks yang menunjukkan bahawa await Ini hanya sah dalam fungsi tak segerak (atau dalam modul yang menyokongnya pada tahap yang lebih tinggi). Mesej ini adalah peringatan bahawa async y await mereka sentiasa berjalan seiring.

Dalam persekitaran di mana kami tidak menggunakan modul atau perlu menyokong pelayar lama, terdapat corak meluas yang terdiri daripada bungkus kod di dalam fungsi async laksana sendiri, Sesuatu seperti (async () => { ... })();Dengan cara ini, keseluruhan blok kekal dalam konteks tak segerak tanpa "mencemarkan" ruang global.

Bagaimana penantian berfungsi dan apa yang sebenarnya dilakukan dengan janji

Perubahan minda yang sebenar datang bersama awaitApabila enjin JavaScript bertemu const resultado = await algunaPromesa; dalam sesuatu fungsi async, jeda pelaksanaan fungsi itu pada ketika itu dan kembali ke gelung acara untuk meneruskan tugasan lain.

Sementara itu, janji itu meneruskan perjalanannya secara bebas. Apabila akhirnya selesai, enjin menyambung semula pelaksanaan fungsi sejurus selepas garisan dengan await, memberikan kepada pembolehubah nilai yang dikembalikan oleh janjiDari perspektif seseorang yang membaca kod, ia kelihatan seperti panggilan segerak yang hanya mengambil masa lebih lama.

  Tapis Pengirim Tidak Diketahui Tidak Terlibat pada iPhone

Apa yang menarik ialah jeda ini Ia tidak menyekat CPUBenang JavaScript utama boleh memproses acara pengguna, animasi, kod tak segerak lain, dsb. Itulah sebabnya kami berkata demikian await Ia lebih kepada a abstraksi sintaksis yang elegan tentang janji cara baharu menjalankan tugas di latar belakang.

Jika anda lebih suka, anda boleh bayangkan bahawa gabungan itu const resultado = await promesa; es promesa.then(valor => { resultado = valor; ... }) sesuatu yang setara, tetapi diedarkan dalam cara linear yang mengelakkan panggilan balik bersarang dan meningkatkan kejelasan aliran.

Satu perincian yang ingin tahu ialah, jika anda beralih ke await objek yang bukan janji tetapi mempunyai kaedah .then()Enjin akan cuba memperlakukannya seolah-olah. Ia akan menyeru itu .then() dengan dua fungsi dalaman iaitu resolusi dan penolakan sangat serupa dengan pembina Promise. Dengan cara ini, await Ia serasi dengan pelaksanaan janji jenis "kemudian".

Ralat mengendalikan dengan async/wait: cuba/tangkap dan janji ditolak

Apabila janji adalah tolak semasa anda menggunakan awaitKesan langsung ialah pengecualian dilemparkan pada baris itu. Dari perspektif kod anda, ia seolah-olah anda telah menulis throw error; betul-betul di mana await, yang menyebabkan pelaksanaan itu melompat ke blok catch paling hampir.

Sebagai contoh, jika anda menggunakan const datos = await obtenerDatos(); dan fungsi obtenerDatos Ia mengembalikan janji yang berakhir dengan kesilapan; aliran akan pergi terus ke blok catch (error) daripada anda try..catchJika anda tidak mempunyai blok tangkapan di sekelilingnya, janji tersirat bahawa fungsi itu kembali async Ia akan ditolak.

Ini bermakna, walaupun mungkin masih ada janji di dalam, apabila anda bekerja dengannya async/menunggu cara semula jadi untuk menangani ralat ia dengan try..catchseperti dalam mana-mana kod JavaScript lain yang membuang pengecualian. Penyatuan gaya ini sangat memudahkan logik dan mengurangkan keperluan untuk mengingati corak yang berbeza bergantung pada sama ada kod itu segerak atau tak segerak.

Jika, secara tidak sengaja, anda terlupa untuk menambah a .catch() kepada janji yang dikembalikan oleh fungsi async Jika gagal, persekitaran akan memaparkan amaran. “janji tidak terurus” (penolakan janji yang tidak terurusSelain itu, anda boleh menggunakan acara global dalam penyemak imbas. unhandledrejection untuk mendaftarkan pengendali yang menangkap semua ralat tersebut dan menghalangnya daripada tidak disedari.

Apabila anda menggabungkan await dengan utiliti seperti Promise.all, satu kesilapan dalam salah satu janji akan menyebarkan janji bersama dan akhirnya menghasilkan pengecualian yang boleh anda tangkap try..catchDengan cara ini, mengurus ralat dalam aliran kerja yang kompleks kekal konsisten dan terpusat.

Async/tunggu dengan mengambil: panggilan API langkah demi langkah

Salah satu penggunaan async/await yang paling biasa ialah mengakses API HTTP menggunakan fungsi tersebut fetch()API ini mengembalikan janji yang diselesaikan kepada objek Response, yang mana anda kemudiannya boleh menggunakan kaedah seperti .json() o .text()yang seterusnya membuat janji-janji baru.

Bayangkan anda ingin merangkum logik meminta data dari titik akhir dalam fungsi. Jika anda mengisytiharkan async function obtenerDatos(), di dalamnya anda boleh tunggu respons rangkaian dengan await fetch(...) dan kemudian mengubah badan menjadi JSON dengan const datos = await respuesta.json(); tanpa perlu merantai beberapa .then().

Untuk memastikan pelayan telah bertindak balas dengan betul, adalah perkara biasa untuk menyemak harta tersebut respuesta.okyang menunjukkan sama ada kod status HTTP berada dalam julat 200-299. Jika tidak, anda boleh membuang ralat secara manual dengan throw new Error('Error en la red');, yang akan menyebabkan catch menangkap keadaan.

Susun keseluruhan aliran dalam a try { ... } catch (error) { ... } Ini menjadikan fungsi tak segerak lebih berdaya tahan: sebarang masalah, sama ada rangkaian, penghuraian JSON atau logik, akan mencetuskan blok tangkapan di mana anda boleh log ralat atau paparkan mesej yang lebih mesra pengguna.

Akhirnya, untuk menggunakan fungsi itu, cukup panggil ia seperti yang lain: obtenerDatos();Ingat bahawa, sebagai tidak segerak, ia mengembalikan janji, jadi dari luar anda perlu memilih sama ada untuk menggunakannya. await obtenerDatos() dalam fungsi lain async atau mengendalikannya dengan .then().catch() jika anda berada dalam konteks bukan tak segerak.

  Petua untuk mengelakkan tol dan lebuh raya menggunakan Peta Apple pada iPhone anda

Jalankan berbilang operasi selari dengan Promise.all dan async/await

Selalunya anda tidak mahu menunggu satu permintaan selesai sebelum memulakan permintaan seterusnya; sebaliknya, anda berminat dengan... melancarkan berbilang operasi tak segerak serentak dan teruskan apabila semuanya telah selesai. Untuk itu, kaedah Promise.all() Ia sesuai dengan sempurna.

Katakan anda perlu menggunakan dua API yang berbeza, sebagai contoh /datos1 y /datos2, dan kemudian menggabungkan maklumat menjadi satu objekDaripada menunggu yang pertama selesai sebelum memulakan yang kedua, anda boleh menulis sesuatu seperti const [r1, r2] = await Promise.all([fetch(url1), fetch(url2)]); dan kedua-dua permohonan akan dibuat secara selari.

Sebaik sahaja anda mempunyai kedua-dua jawapan, anda boleh memohon await pada setiap satu untuk mengubahnya menjadi JSON: const d1 = await r1.json(); const d2 = await r2.json();Akhirnya, ia sangat biasa menggabungkan data dengan pengendali penyebaran: const datosCombinados = { ...d1, ...d2 };, yang mencipta struktur unik yang menggabungkan sifat kedua-duanya.

Keseluruhan blok ini hendaklah dibalut dengan a try..catchkerana sebarang kegagalan dalam salah satu permintaan akan menyebabkan Promise.all() ditolak. Terima kasih kepada async/menunggu, mengendalikan jenis senario ini dengan operasi serentak Ia secara visual mudah tetapi sangat berkuasa dari segi prestasi.

Corak ini amat berguna apabila aplikasi web anda memerlukan beberapa sumber bebas sebelum paparan boleh diberikan: contohnya, mendapatkan konfigurasi, data pengguna dan statistik penggunaan secara serentak, mengurangkan masa menunggu keseluruhan.

Kelebihan sebenar async/menunggu berbanding janji dan panggilan balik "tulen".

Penggunaan async/await menawarkan beberapa faedah praktikal Faedah ini dapat dilihat dari contoh terawal hingga aplikasi berskala besar. Yang paling jelas ialah kebolehbacaan: aliran ditulis dari atas ke bawah tanpa memerlukan fungsi bersarang atau berantai. .then() satu demi satu.

Titik kuat lain ialah kebolehselenggaraan kodDengan lebih banyak blok linear, lebih mudah untuk memperkenalkan perubahan, mengekstrak bahagian ke dalam fungsi tambahan atau menggunakan semula logik. Ini secara langsung mengakibatkan lebih sedikit ralat dan keluk pembelajaran yang lebih lancar untuk pendatang baru dalam projek itu.

Ralat mengendalikan dengan try..catch bukannya berbilang .catch() berselerak Ia membantu memusatkan logik kesalahan. Anda boleh mengelilingi beberapa await dengan satu blok dan melaksanakan dasar pengurusan ralat yang konsisten, tanpa kehilangan perincian pada baris mana masalah berlaku.

Dari sudut prestasi, async/waiit tidak menjadikan kod "lebih pantas" dengan sendirinya, tetapi ia boleh menggalakkan anda menggunakan corak seperti Promise.all() untuk melaksanakan tugas secara selari di mana anda mungkin telah menjalankannya secara bersiri sebelum ini. Hasilnya ialah kurang jumlah masa menunggu untuk pengguna akhir.

Tambahan pula, async/wait adalah serasi dengan janji tradisionalAnda tidak perlu menulis semula semua kod anda untuk menerima pakainya. Anda boleh menggabungkan fungsi yang menggunakannya. .then() dengan orang lain yang menggunakan await Tiada masalah, yang memudahkan untuk memindahkan projek secara beransur-ansur.

Dalam ekosistem moden, dalam penyemak imbas dan dalam Node.js, kebanyakan alat dan perpustakaan sudah bergantung pada janji dan async/menunggu. Ini menjadikan pembelajaran konsep ini dengan baik bukan pilihan, tetapi penting. keperluan untuk bekerja dengan JavaScript moden dalam projek profesional.

Seluruh set idea ini—janji, tidak segerak/menunggu, fetch, Promise.allTry/catch dan glosari istilah utama membentuk rangka kerja yang sangat kukuh untuk menulis kod tak segerak yang jelas, boleh dibaca dan teguhMenguasainya membolehkan anda membina aplikasi web moden yang bertindak balas dengan cepat, memanfaatkan rangkaian dengan baik dan lebih mudah diselenggara dari semasa ke semasa.