- Umaasa ang Async/wait sa mga pangakong mag-alok ng mas nababasang asynchronous na code, na mas malapit sa tradisyonal na kasabay na istilo.
- Ang mga function ng Async ay palaging nagbabalik ng isang pangako at nagbibigay-daan sa iyong gamitin ang paghihintay upang i-pause ang kanilang pagpapatupad nang hindi hinaharangan ang pangunahing thread.
- Ang paghawak ng error sa try/catch at mga utility tulad ng Promise.all ay nagpapadali sa pagkontrol ng mga pagkabigo at pagsasama-sama ng ilang operasyon nang magkatulad.
- Ang pinagsamang paggamit ng mga pangako, async/wait, at mga API tulad ng fetch ay ang pundasyon ng modernong network-oriented na pag-develop ng JavaScript.
Ang asynchronous programming sa JavaScript ay naging mahalaga sa modernong web development: Ang mga API request, database access , file reading, o anumang operasyon na tumatagal nang higit sa isang sandali ay nakasalalay dito upang mapanatili ang isang maayos na user interface. Dahil sa mga promises , async/await, at mga API, mayroon tayong isang makapangyarihang hanay ng mga tool upang kontrolin ang daloy na ito nang hindi hinaharangan ang application.
Sa loob ng maraming taon ang pattern ay pangunahing ginagamit mga callback at nakakadena na pangakona, bagama't mahusay ang mga ito, ay maaaring magtapos sa kasumpa-sumpa na "callback hell" o sa walang katapusang mga tanikala ng .then() y .catch() mahirap sundin. Sa pagdating ng async/naghihintay sa ECMAScript 2017Ang JavaScript ay gumawa ng isang malaking hakbang sa pagiging madaling mabasa, na nagpapahintulot sa asynchronous na code na maisulat sa isang istilo na halos kapareho ng tradisyonal na kasabay na code.
Ano ang asynchronous programming sa JavaScript at bakit ito napakahalaga?
Ang asynchronous programming ay isang paraan ng pag-oorganisa ng code upang makapagsimula ang isang gawain at maipagpatuloy ng programa ang pagsasagawa ng iba pang mga bagay nang hindi "napipigilan" sa paghihintay ng tugon. Sa JavaScript, mahalaga ito dahil ang wika ay tumatakbo, sa browser at sa Node.js, sa isang pangunahing thread na humahawak sa parehong lohika at interface.
Kapag nagpadala ka ng HTTP request sa isang API , nagbasa ng file, o nag-query sa database, ang mga operasyong ito ay maaaring tumagal mula milliseconds hanggang ilang segundo. Kung ang mga ito ay synchronous, makikita ng user na naka-lock ang page at hindi makakapag-interact. Gamit ang asynchronous model, itinatalaga ng JavaScript engine ang mga gawaing ito at, pansamantala, maaaring magpatuloy sa pag-render ng UI, paghawak ng mga event, at pagpapatupad ng iba pang mga script.
Sa simula, ang karaniwang mekanismo para sa pagtugon kapag natapos na ang isang operasyon ay ang pagpasa ng isang callback function bilang isang argumento. Ang function na iyon ay isasagawa kasama ang resulta o error. Ang problema ay ang pag-chain ng mga callback sa loob ng iba pang mga callback ay lumilikha ng kinatatakutang callback hell : labis na naka-indent na code na mahirap basahin, i-debug, at panatilihin.
Upang malutas ang ilan sa kaguluhang iyon, lumitaw ang sumusunod: ipinapangakona nakapaloob sa resulta ng isang asynchronous na operasyon at nagbibigay-daan sa mga aksyon na i-chain kasama ng .then() at pamahalaan ang mga pagkabigo gamit ang .catch()Ito ay isa nang mahusay na pagpapabuti, ngunit iniwan pa rin nito ang code na puno ng mga callback na "nakakaila" sa likod ng mga pamamaraang iyon.
Mga Pangako: ang pundasyon ng async/naghihintay
Bago maunawaan ang async/await, mahalagang malinaw na tukuyin kung ano ang isang promise sa JavaScript . Ang promise ay isang object na kumakatawan sa resulta ng isang asynchronous operation sa hinaharap: isang bagay na hindi pa nangyayari ngunit mangyayari sa ibang pagkakataon, matagumpay man o hindi.
Ang isang karaniwang pangako ay maaaring nasa isa sa tatlong mahusay na natukoy na estado: nakabinbin habang isinasagawa ang operasyon, natutupad kapag matagumpay itong nakumpleto at nakagawa ng isang halaga, o tinanggihan kapag nabigo ito at nakabuo ng isang error. Ang estado ng pangako ang nagtatakda kung aling mga callback ang susunod na isasagawa.
Kapag gumawa ka ng pangako gamit ang tagapagbuo PromiseIpapasa mo ito sa isang executable function na tumatanggap ng dalawang argumento: resolve y rejectKung maayos ang operasyon, tumawag ka resolve(valor)Kung may nangyaring problema, humihiling ka reject(error)Pagkatapos, mula sa labas, maaari mong gamitin miPromesa.then() upang iproseso ang resulta at .catch() upang pamahalaan ang mga error.
Bilang karagdagan sa mga pangakong ginawa ng kamay, marami nang mga modernong API ng wika Tinutupad nila ang isang serye na pangako.. Pag-andar fetch()Halimbawa, sinisimulan nito ang isang kahilingan sa HTTP at agad na nagbabalik ng pangako na sa huli ay malulutas sa isang bagay. Response o tinanggihan kung mayroong pagkabigo sa network.
Upang gumana sa maraming gawain nang magkatulad, nag-aalok ang JavaScript ng mga kagamitan tulad ng Promise.all()Ang pamamaraang ito ay tumatagal ng isang hanay ng mga pangako at nagbabalik ng isang bagong pangako na malulutas lamang kapag ang lahat ng mga pangako ay matagumpay na nakumpleto, o tinatanggihan kung alinman sa mga ito ay nabigo. Ito ay lalong kapaki-pakinabang kapag gusto mo pagsamahin ang data mula sa iba't ibang mapagkukunan bago magpatuloy.
Mga pangunahing konsepto: async, naghihintay, at ang modelo ng error
Ang syntax ng async/wait ay binuo sa mga pangakoHindi nito pinapalitan ang mga ito. Ang ginagawa nito ay nagbibigay ng isang mas maginhawa, mas malinaw na paraan, mas malapit sa kasabay na programming, upang gumana sa kanila, binabawasan ang visual na ingay ng .then() nakakadena.
Ang susing salita async Ito ay inilalagay bago ang isang function upang sabihin sa JavaScript engine na ang function ay gagana nang asynchronously at na, anuman ang mangyari sa loob, ay palaging tutuparin ang isang pangakoKahit na ibalik mo ang isang normal na halaga, awtomatikong ibalot ito ng makina Promise.resolve(valor).
Para sa bahagi nito, ang nakalaan na salita await maaari lamang gamitin sa loob ng isang function na ipinahayag bilang asyncAng tungkulin nito ay i-pause ang execution sa loob ng function na iyon hanggang sa matupad ang pangakong ipinasa dito. maresolba o tatanggihan, direktang ibinabalik ang nalutas na halaga o naghagis ng eksepsiyon kung ang pangako ay nagtatapos sa isang error.
kapag ginamit mo await promesa at ang pangako ay malulutas, makukuha mo ang resulta na parang ito ay isang kasabay na tawag. Kung sa halip ang pangako ay tinanggihan, Ang isang pagbubukod ay nabuo sa puntong iyon., katumbas ng paggawa ng a throw errorNagbibigay-daan ito sa muling paggamit ng parehong mga istruktura sa paghawak ng error tulad ng sa kasabay na code, gaya ng try..catch.
Sa pamamagitan ng pagbabalot ng aming mga asynchronous na tawag sa isang bloke try { ... } catch (error) { ... }Maaari naming makuha ang mga kaso kung saan nabigo ang alinman sa mga pangako, magpakita ng naaangkop na mga mensahe sa user, o gumawa ng mga pagpapasya tulad ng muling pagsubok, pag-redirect, o pag-log sa pagkabigo sa isang panlabas na system.
Ang keyword na async: mga function na palaging nagbabalik ng mga pangako
Lugar async sa harap ng isang function Ito ay may dalawang napakahalagang kahihinatnan: sa isang banda, pinipilit nitong palaging maging pangako ang ibinalik na halaga; sa kabilang banda, pinapagana nito ang paggamit ng await sa loob ng katawan ng function na iyon, na ganap na nagbabago kung paano nakaayos ang asynchronous na daloy.
Kung magdedeklara ka ng isang bagay tulad ng async function sumar() { return 1; }Bagama't ito ay tila isang normal na paggana, ang talagang nakukuha mo ay a function na nagbabalik ng dati nang nalutas na pangako sa tapang 1Sa labas ng iyong system, kakailanganin mong i-access ang resulta gamit ang await sumar() may sumar().then() kung mas gusto mo ang istilong nakakadena.
Maaari mo ring tahasang ibalik ang isang pangako mula sa isang function. async, Halimbawa return Promise.resolve(1);at ang pag-uugali ay magiging pareho. Sa parehong mga kaso, ang function ay nakahanay sa promise model, na nagpapadali sa kumbinasyon nito sa iba pang mga asynchronous na function at utility gaya ng Promise.all().
Karaniwan na, kapag nagsisimula tayo, nakalimutan nating markahan ang isang function bilang ganoon async at gayunpaman ginagamit namin await sa loobSa sitwasyong iyon, maglalagay ang JavaScript ng isang error sa syntax na nagpapahiwatig na await Valid lang ito sa mga asynchronous na function (o sa mga module na sumusuporta dito sa mas mataas na antas). Ang mensaheng ito ay isang paalala na async y await lagi silang magkasabay.
Sa mga kapaligiran kung saan hindi kami gumagamit ng mga module o kailangang suportahan ang mga mas lumang browser, mayroong malawak na pattern na binubuo ng balutin ang code sa loob ng isang self-executing async function, parang (async () => { ... })();Sa ganitong paraan, nananatili ang buong block sa loob ng isang asynchronous na konteksto nang hindi "nakontamina" ang pandaigdigang espasyo.
Paano gumagana ang paghihintay at kung ano talaga ang ginagawa nito sa mga pangako
Ang tunay na pagbabago ng mindset ay kasama awaitKapag nakatagpo ang JavaScript engine const resultado = await algunaPromesa; sa loob ng isang function async, i-pause ang execution ng function na iyon sa puntong iyon at babalik sa loop ng kaganapan upang magpatuloy sa pagdalo sa iba pang mga gawain.
Samantala, ang pangako ay nagpapatuloy sa kanyang kurso nang nakapag-iisa. Kapag ito ay tuluyang nalutas, ang makina ay nagpatuloy sa pagpapatupad ng function pagkatapos mismo ng linya sa await, pagtatalaga sa variable ang halagang ibinalik ng pangakoMula sa pananaw ng isang taong nagbabasa ng code, mukhang isang kasabay na tawag na medyo mas matagal.
Ang kawili-wili ay ang pag-pause na ito Hindi nito hinaharangan ang CPUAng pangunahing thread ng JavaScript ay maaaring magproseso ng mga kaganapan ng user, mga animation, iba pang asynchronous na code, atbp. Kaya naman sinasabi namin iyan await Ito ay higit pa sa isang eleganteng syntactic abstraction tungkol sa mga pangako ng isang bagong paraan ng pagpapatakbo ng mga gawain sa background.
Kung gusto mo, maaari mong isipin na ang kumbinasyon const resultado = await promesa; es promesa.then(valor => { resultado = valor; ... }) ng isang bagay na katumbas, ngunit ipinamahagi sa isang linear na paraan na umiiwas sa mga nested callback at nagpapahusay sa kalinawan ng daloy.
Ang isang kakaibang detalye ay iyon, kung lilipat ka sa await isang bagay na hindi pangako ngunit may pamamaraan .then()Susubukan ng makina na tratuhin ito na parang ito. Tatawagin nito iyon .then() na may dalawang panloob na function ng resolusyon at pagtanggi halos kapareho sa mga tagabuo ng Promise. Sa ganitong paraan, await Ito ay katugma sa mga pagpapatupad ng "thenable" na uri ng mga pangako.
Error sa paghawak sa async/wait: subukan/huli at tinanggihan ang mga pangako
Kapag ang isang pangako ay tanggihan habang ginagamit mo awaitAng direktang epekto ay ang isang pagbubukod ay itinapon sa linyang iyon. Mula sa pananaw ng iyong code, para kang nagsulat throw error; tama kung saan ang await, na nagiging sanhi upang tumalon ang pagpapatupad na iyon sa block catch pinakamalapit.
Halimbawa, kung gagamitin mo const datos = await obtenerDatos(); at ang pagpapaandar obtenerDatos Nagbabalik ito ng pangako na nagtatapos sa isang pagkakamali; ang daloy ay direktang pupunta sa bloke catch (error) mula sa iyong try..catchKung wala kang capture block sa paligid nito, ang implicit na pangako na babalik ang function async Tatanggihan ito.
Nangangahulugan ito na, kahit na maaaring may mga pangako pa rin sa loob, kapag nagtatrabaho ka async/hintayin ang natural na paraan upang mahawakan ang mga error kasama ni try..catchtulad ng sa anumang iba pang JavaScript code na nagtatapon ng mga pagbubukod. Ang pagsasama-sama ng mga istilo na ito ay lubos na nagpapasimple sa lohika at binabawasan ang pangangailangan na matandaan ang iba't ibang mga pattern depende sa kung ang code ay kasabay o asynchronous.
Kung, sa pagkakamali, nakalimutan mong magdagdag ng a .catch() sa pangakong ibinalik ng isang function async Kung nabigo ito, magpapakita ng babala ang kapaligiran. "pangako na hindi pinamamahalaan" (hindi nahawakang pagtanggi sa pangakoBilang karagdagan, maaari mong gamitin ang pandaigdigang kaganapan sa browser. unhandledrejection upang magrehistro ng isang handler na kumukuha ng lahat ng mga error na iyon at pinipigilan ang mga ito na hindi mapansin.
Kapag pinagsama mo await na may mga kagamitan tulad ng Promise.all, isang pagkakamali sa isa sa mga pangako ay nagpapalaganap ng magkasanib na pangako at sa wakas ay nagreresulta sa isang pagbubukod na maaari mong makuha try..catchSa ganitong paraan, nananatiling pare-pareho at sentralisado ang pamamahala ng mga error sa mga kumplikadong daloy ng trabaho.
Async/wait with fetch: step-by-step na API calls
Isa sa mga pinakakaraniwang gamit ng async/wait ay ang pag-access Mga HTTP API gamit ang function fetch()Ang API na ito ay nagbabalik ng isang pangako na lumulutas sa isang bagay Response, kung saan maaari kang gumamit ng mga pamamaraan tulad ng .json() o .text()na gumagawa naman ng mga bagong pangako.
Isipin na gusto mong i-encapsulate ang lohika ng paghiling ng data mula sa isang endpoint sa isang function. Kung magdedeklara ka async function obtenerDatos(), sa loob nito ay magagawa mo maghintay para sa tugon ng network na may await fetch(...) at pagkatapos ay ibahin ang katawan sa JSON gamit ang const datos = await respuesta.json(); nang hindi kailangang i-chain ang ilan .then().
Upang matiyak na tumugon nang tama ang server, karaniwan nang suriin ang property respuesta.okna nagpapahiwatig kung ang HTTP status code ay nasa hanay na 200-299. Kung hindi, maaari kang manu-manong magtapon ng error sa throw new Error('Error en la red');, na magdudulot ng catch makuha ang sitwasyon.
Ayusin ang buong daloy sa loob ng a try { ... } catch (error) { ... } Ginagawa nitong mas nababanat ang asynchronous function: anumang problema, network man, JSON parsing, o logic-related, ay magti-trigger ng capture block kung saan mo magagawa. i-log ang error o magpakita ng mas madaling gamitin na mensahe.
Sa huli, para magamit ang function, tawagan lang ito gaya ng iba: obtenerDatos();Tandaan na, bilang asynchronous, nagbabalik ito ng isang pangako, kaya mula sa labas ay kailangan mong piliin kung gagamitin ito. await obtenerDatos() sa loob ng ibang function async o hawakan ito gamit .then().catch() kung ikaw ay nasa di-asynchronous na konteksto.
Magsagawa ng maramihang mga operasyon na kahanay ng Promise.all at async/wait
Kadalasan hindi mo gustong maghintay na matapos ang isang kahilingan bago simulan ang susunod; sa halip, interesado ka sa... maglunsad ng maraming asynchronous na operasyon nang sabay-sabay at magpatuloy kapag natapos na ang lahat. Para doon, ang pamamaraan Promise.all() Tamang-tama ito.
Ipagpalagay na kailangan mong gumamit ng dalawang magkaibang API, halimbawa /datos1 y /datos2, at mamaya pagsamahin ang impormasyon sa isang bagaySa halip na hintayin na makumpleto ang una bago simulan ang pangalawa, maaari kang magsulat ng isang bagay tulad ng const [r1, r2] = await Promise.all([fetch(url1), fetch(url2)]); at ang parehong mga aplikasyon ay gagawin nang magkatulad.
Kapag mayroon ka nang parehong sagot, maaari kang mag-apply await sa bawat isa upang baguhin ang mga ito sa JSON: const d1 = await r1.json(); const d2 = await r2.json();Sa wakas, ito ay napakakaraniwan pagsamahin ang data kasama ang propagation operator: const datosCombinados = { ...d1, ...d2 };, na lumilikha ng isang natatanging istraktura na pinagsasama ang mga katangian ng pareho.
Ang buong bloke na ito ay dapat na balot sa isang try..catchdahil ang anumang pagkabigo sa isa sa mga kahilingan ay magdudulot Promise.all() ay tinatanggihan. Salamat sa pag-async/paghihintay, paghawak sa mga ganitong uri ng mga senaryo gamit ang sabay-sabay na operasyon Ito ay biswal na simple ngunit napakalakas sa mga tuntunin ng pagganap.
Ang pattern na ito ay lalong kapaki-pakinabang kapag ang iyong web application ay nangangailangan ng ilang magkakahiwalay na mapagkukunan bago ito makapag-render ng isang view: halimbawa, ang pagkuha ng mga setting, data ng user, at mga istatistika ng paggamit nang sabay-sabay, na binabawasan ang kabuuang oras ng paghihintay.
Mga tunay na pakinabang ng async/paghihintay kumpara sa mga "puro" na pangako at callback
Gamitin Nag-aalok ang async/wait ng ilang praktikal na benepisyo Ang mga benepisyong ito ay kapansin-pansin mula sa pinakaunang mga halimbawa hanggang sa malakihang mga aplikasyon. Ang pinaka-halata ay ang pagiging madaling mabasa: ang daloy ay nakasulat mula sa itaas hanggang sa ibaba nang hindi nangangailangan ng nested o chained function. .then() sunod sunod.
Isa pang kalakasan ay ang pagpapanatili ng code . Sa mas maraming linear blocks, mas madaling magpasok ng mga pagbabago, kumuha ng mga bahagi sa mga auxiliary function, o muling gamitin ang logic. Direktang nagreresulta ito sa mas kaunting mga error at mas maayos na learning curve para sa mga baguhan sa proyekto.
Error sa paghawak sa try..catch sa halip na maramihan .catch() nagkalat Nakakatulong ito na isentro ang lohika ng pagkakamali. Maaari mong palibutan ang ilan await na may iisang bloke at magpatupad ng pare-parehong patakaran sa pamamahala ng error, nang hindi nawawala ang detalye kung saang linya naganap ang problema.
Mula sa pananaw sa pagganap, hindi ginagawang "mas mabilis" ng async/wait ang code nang mag-isa, ngunit maaari ka nitong hikayatin na gumamit ng mga pattern tulad ng Promise.all() upang maisagawa ang mga gawain nang magkatulad kung saan maaaring nauna mong pinatakbo ang mga ito nang sunud-sunod. Ang resulta ay mas kaunting oras ng paghihintay para sa end user.
Higit pa rito, ang async/wait ay tugma sa tradisyonal na mga pangakoHindi mo kailangang muling isulat ang lahat ng iyong code para ma-adopt ito. Maaari mong pagsamahin ang mga function na gumagamit nito. .then() kasama ng iba pang gumagamit await Walang problema, na nagpapadali sa paglipat ng mga proyekto nang paunti-unti.
Sa modernong ecosystem, kapwa sa mga browser at sa Node.js, karamihan sa mga tool at library ay umaasa na sa mga promise at async/await. Dahil dito, ang pag-master sa mga konseptong ito ay hindi opsyonal, kundi isang kinakailangan para sa paggamit ng modernong JavaScript sa mga propesyonal na proyekto.
Ang buong hanay ng mga ideyang ito—mga pangako, async/naghihintay, fetch, Promise.allAng try/catch at glossary ng mga pangunahing termino ay bumubuo ng isang napaka-solid na balangkas para sa pagsulat malinaw, nababasa, at matatag na asynchronous na codeAng pag-master sa mga ito ay nagbibigay-daan sa iyo na bumuo ng mga modernong web application na mabilis na tumugon, nakikinabang nang husto sa network, at mas madaling mapanatili sa paglipas ng panahon.
Masigasig na manunulat tungkol sa mundo ng mga byte at teknolohiya sa pangkalahatan. Gustung-gusto kong ibahagi ang aking kaalaman sa pamamagitan ng pagsusulat, at iyon ang gagawin ko sa blog na ito, ipakita sa iyo ang lahat ng mga pinaka-kagiliw-giliw na bagay tungkol sa mga gadget, software, hardware, teknolohikal na uso, at higit pa. Ang layunin ko ay tulungan kang mag-navigate sa digital na mundo sa simple at nakakaaliw na paraan.