Модерни ЈаваСкрипт туторијал: Обећања, асинхронизација/чекање и API-ји

Последње ажурирање: 04/12/2025
Аутор: Исак
  • Async/await се ослања на обећања да ће понудити читљивији асинхрони код, ближи традиционалном синхроном стилу.
  • Асинхроне функције увек враћају обећање и омогућавају вам да користите команду await да паузирате њихово извршавање без блокирања главне нити.
  • Обрада грешака помоћу try/catch и услужних програма попут Promise.all олакшава контролу кварова и комбиновање неколико операција паралелно.
  • Комбинована употреба обећања, async/await и API-ја попут fetch-а је основа модерног мрежно оријентисаног JavaScript развоја.

js

La програмирање асинхроно у Јаваскрипту постао је неопходан у модерном веб развоју: API захтеви, приступ базе податакаЧитање датотеке или било која операција која траје дуже од тренутка зависи од тога како би интерфејс радио глатко. Захваљујући обећања, асинхронизација/чекање и API-ји Имамо веома моћан скуп алата за контролу тог тока без блокирања апликације.

Годинама се образац углавном користио повратни позиви и ланчана обећањакоје, иако веома добро функционишу, могу да се заврше у озлоглашеном „паклу повратних позива“ или у бескрајним ланцима .then() y .catch() тешко је пратити. Са доласком асинхронизација/чекање у ECMAScript-у 2017Јаваскрипт је направио огроман скок у читљивости, омогућавајући писање асинхроног кода у стилу готово идентичном традиционалном синхроном коду.

Шта је асинхроно програмирање у ЈаваСкрипту и зашто је толико важно?

La асинхроно програмирање То је начин организовања кода тако да задатак може да почне и да програм може да настави са извршавањем других ствари без „замрзавања“ чекања на одговор. У JavaScript-у је ово од виталног значаја јер језик ради, у прегледачу и у Node.js-у, на једна главна нит који се бави и логиком и интерфејсом.

Када баците HTTP захтев ка API-јуКада читате датотеку или упућујете упит бази података, ове операције могу трајати од милисекунди до неколико секунди. Ако би биле синхроне, корисник би видео страницу закључану и не би могао да интерагује. Код асинхроног модела, JavaScript механизам делегира ове задатке и може да настави са радом у међувремену. цртање корисничког интерфејса, руковање догађајима и покретање других скрипти.

Првобитно, стандардни механизам за реаговање када се операција заврши био је прослеђивање функција повратног позива као аргумент. Та функција је касније извршена са резултатом или грешком. Проблем је у томе што, ланчаним повратним позивима унутар других повратних позива, страшни повратни пакао: код са превише увлачења, тежак за читање, дебаговање и одржавање.

Да би се решио део тог хаоса, појавило се следеће: обећавакоји обухватају резултат асинхроне операције и омогућавају ланчано повезивање акција са .then() и управљати неуспесима помоћу .catch()Ово је већ било велико побољшање, али је и даље остављало код пун повратних позива „маскираних“ иза тих метода.

Обећања: темељи асинхроности/чекања

Пре него што схватимо async/await, важно је да буде веома јасно шта је обећање у ЈаваскриптуОбећање је објекат који представља будући резултат асинхроне операције: нешто што се још није догодило, али ће се догодити касније, било успешно или неуспешно.

А стандардно обећање може се наћи у једном од три добро дефинисана стања: на чекању (нерешен) док је операција у току, завршено (испуњено) када се добро заврши и произведе вредност, или се одбије (одбијен) када не успе и генерише грешку. То стање обећања одређује које ће се повратне функције следеће извршити.

Када креирате обећање користећи конструктор PromiseПрослеђујете му извршну функцију која прима два аргумента: resolve y rejectАко операција прође добро, зовете resolve(valor)Ако дође до проблема, позивате се reject(error)Затим, споља, можете користити miPromesa.then() да обради резултат и .catch() да управља грешкама.

Поред ручно израђених обећања, многи модерни језички API-ји већ Испуњавају серијско обећање.. Функција fetch()На пример, покреће HTTP захтев и одмах враћа обећање које ће се на крају решити објектом. Response или одбијено ако дође до квара мреже.

За паралелни рад са више задатака, Јаваскрипт нуди алате као што су Promise.all()Ова метода узима низ обећања и враћа ново обећање које се решава само када су сва обећања успешно завршена или се одбацује ако било које од њих не успе. Ово је посебно корисно када желите комбинују податке из различитих извора пре даљег.

  Креирање скрипти за одржавање помоћу Аутоматора на macOS-у: комплетан водич и примери

Кључни концепти: асинхроност, чекање и модел грешке

Синтакса оф async/await је заснован на обећањимаНе замењује их. Оно што ради јесте да пружа практичнији, јаснији начин, ближи синхроном програмирању, за рад са њима, смањујући визуелну буку... .then() окован ланцима.

Кључна реч async Поставља се испред функције да би се JavaScript механизму рекло да ће функција радити асинхроно и да, шта год да се деси унутра, увек ће одржати обећањеЧак и ако вратите нормалну вредност, мотор ће је аутоматски уклопити у Promise.resolve(valor).

Са своје стране, резервисана реч await може се користити само унутар функције декларисане као asyncЊегова функција је да паузира извршавање унутар те функције док се не испуни обећање које му је дато. бити решен или одбијен, директно враћајући решену вредност или бацајући изузетак ако се обећање заврши грешком.

када користите await promesa и обећање се реши, добијате резултат као да је у питању синхрони позив. Ако се уместо тога обећање одбије, У том тренутку се генерише изузетак., еквивалентно обављању throw errorОво омогућава поновну употребу истих структура за обраду грешака као у синхроном коду, као што је try..catch.

Умотавањем наших асинхроних позива у блок try { ... } catch (error) { ... }Можемо да забележимо случајеве у којима било које од обећања не успе, прикажемо одговарајуће поруке кориснику или донесемо одлуке као што су поновни покушај, преусмеравање или евидентирање неуспеха на спољни систем.

Кључна реч async: функције које увек враћају обећања

Место async испред функције Ово има две веома важне последице: с једне стране, приморава да повратна вредност увек буде обећање; с друге стране, омогућава употребу await унутар тела те функције, што потпуно мења начин на који је асинхрони ток структуриран.

Ако декларишете нешто попут async function sumar() { return 1; }Иако може изгледати као нормална функција, оно што заправо добијате је функција која враћа претходно решено обећање са вредношћу 1Ван вашег система, мораћете да приступите том резултату користећи await sumar() или са sumar().then() ако више волите ланчани стил.

Такође можете експлицитно вратити обећање из функције. async, на пример return Promise.resolve(1);и понашање ће бити исто. У оба случаја, функција је усклађена са моделом обећања, што олакшава њену комбинацију са другим асинхроним функцијама и услужним програмима као што су Promise.all().

Веома је уобичајено да, када почињемо, заборавимо да означимо функцију као такву. async а ипак користимо await ДентроУ тој ситуацији, Јаваскрипт ће избацити синтаксичку грешку која указује на то await Ово важи само у асинхроним функцијама (или у модулима који то подржавају на вишем нивоу). Ова порука је подсетник да async y await увек иду руку под руку.

У окружењима где не користимо модуле или морамо да подржавамо старије прегледаче, постоји широко распрострањен образац који се састоји од умотајте код унутар самоизвршавајуће асинхроне функције, Нешто слично (async () => { ... })();На овај начин, цео блок остаје унутар асинхроног контекста без „контаминације“ глобалног простора.

Како await функционише и шта заправо ради са обећањима

Права промена начина размишљања долази са awaitКада JavaScript мотор наиђе на const resultado = await algunaPromesa; унутар функције async, паузирати извршавање те функције у том тренутку и враћа се у петљу догађаја да би наставио да се бави другим задацима.

У међувремену, обећање наставља свој ток независно. Када се коначно реши, механизам наставља извршавање функције одмах након линије са await, додељујући променљивој вредност коју враћа обећањеИз перспективе некога ко чита код, изгледа као синхрони позив који само траје мало дуже.

  На мом Андроид телефону или на мом рачунару| Са мог рачунара и мог Андроид телефона

Занимљиво је да ова пауза Не блокира процесорГлавна JavaScript нит може да обрађује корисничке догађаје, анимације, други асинхрони код итд. Зато кажемо да await То је више од елегантна синтаксичка апстракција о обећањима новог начина извршавања задатака у позадини.

Ако више волите, можете замислити ту комбинацију const resultado = await promesa; es promesa.then(valor => { resultado = valor; ... }) нечег еквивалентног, али дистрибуираног на линеаран начин који избегава угнежђене повратне позиве и побољшава јасноћу тока.

Један занимљив детаљ је да, ако се преселите у await објекат који није обећање, али има метод .then()Мотор ће покушати да га третира као да јесте. Позваће то .then() са две унутрашње функције резолуција и одбијање веома сличне онима градитеља Promise. Овуда, await Компатибилан је са имплементацијама обећања типа „thenable“.

Обрада грешака са async/await: try/catch и одбијена обећања

Када је обећање одбијте док користите awaitДиректан ефекат је да се у тој линији избацује изузетак. Из перспективе вашег кода, то је као да сте написали throw error; тачно тамо где await, што узрокује да то извршавање скочи на блок catch најближи.

На пример, ако користите const datos = await obtenerDatos(); и функцију obtenerDatos Враћа обећање које се завршава грешком; ток ће ићи директно до блокирање catch (error) од вас try..catchАко немате блок за снимање око њега, имплицитно обећање да функција враћа async Биће одбијено.

То значи да, иако унутра још увек могу бити обећања, када радите са async/wait је природан начин за обраду грешака то је са try..catchкао и у било ком другом JavaScript коду који баца изузетке. Ово обједињавање стилова знатно поједностављује логику и смањује потребу за памћењем различитих образаца у зависности од тога да ли је код синхрони или асинхрони.

Ако грешком заборавите да додате .catch() обећању које враћа функција async Ако не успе, окружење ће приказати упозорење. „Неуправљано обећање“ (необрађено одбијање обећањаПоред тога, можете користити глобални догађај у прегледачу. unhandledrejection да региструје програм за обраду података који бележи све те грешке и спречава да остану непримећене.

Када комбинујете await са комуналним услугама као што су Promise.all, једна грешка у једном од обећања ће пропагира заједничко обећање и коначно резултира изузетком који можете ухватити помоћу try..catchНа овај начин, управљање грешкама у сложеним токовима рада остаје доследно и централизовано.

Асинхронизација/чекање са дохватом: API позиви корак по корак

Једна од најчешћих употреба async/await је приступ HTTP API-ји који користе функцију fetch()Овај API враћа обећање које се решава у објекат Response, на којем затим можете позвати методе као што су .json() o .text()што заузврат доноси нова обећања.

Замислите да желите да инкапсулирате логику захтевања података од крајње тачке у функцији. Ако декларишете async function obtenerDatos(), унутар њега можете сачекајте одговор мреже са await fetch(...) а затим трансформишите тело у JSON помоћу const datos = await respuesta.json(); без потребе за ланцем неколико .then().

Да би се осигурало да је сервер исправно одговорио, уобичајено је проверити својство respuesta.okшто показује да ли је HTTP статусни код у опсегу од 200 до 299. Ако није, можете ручно избацити грешку помоћу throw new Error('Error en la red');, што ће проузроковати catch ухватити ситуацију.

Организујте цео ток унутар try { ... } catch (error) { ... } Ово чини асинхрону функцију много отпорнијом: било који проблем, било да је мрежни, JSON парсирање или логички, покренуће блок за снимање где можете забележи грешку или прикажи поруку која је једноставнија за коришћење.

На крају крајева, да бисте користили функцију, једноставно је позовите као и било коју другу: obtenerDatos();Запамтите да, будући да је асинхрон, враћа обећање, тако да ћете споља морати да изаберете да ли ћете га користити. await obtenerDatos() унутар друге функције async или се тиме носити са .then().catch() ако се налазите у неасинхроном контексту.

  Сазнајте како да добијете свој бесплатни налог на Гоогле диску

Извршите више операција паралелно са Promise.all и async/await

Често не желите да чекате да се један захтев заврши пре него што започнете следећи; уместо тога, заинтересовани сте за... покрените више асинхроних операција одједном и наставити када сви заврше. За то, метода Promise.all() савршено се уклапа.

Претпоставимо да треба да користите два различита API-ја, на пример /datos1 y /datos2, а касније спојити информације у један објекатУместо да чекате да се први заврши пре него што започнете други, можете написати нешто попут const [r1, r2] = await Promise.all([fetch(url1), fetch(url2)]); и обе пријаве ће бити поднете паралелно.

Када добијете оба одговора, можете се пријавити await о сваком од њих да би их трансформисали у JSON: const d1 = await r1.json(); const d2 = await r2.json();Коначно, веома је често комбинујте податке са оператором пропагације: const datosCombinados = { ...d1, ...d2 };, што ствара јединствену структуру која спаја својства оба.

Читав овај блок треба да буде умотан у try..catchјер ће сваки неуспех у једном од захтева проузроковати Promise.all() је одбијено. Захваљујући async/await, руковање овим типовима сценарија са истовремене операције Визуелно је једноставан, али веома моћан у погледу перформанси.

Овај образац је посебно користан када ваша веб апликација захтева неколико независних ресурса пре него што се приказ може приказати: на пример, истовремено добијање конфигурације, корисничких података и статистике коришћења, смањујући укупно време чекања.

Праве предности async/await у односу на „чиста“ обећања и повратне позиве

Употреба async/await нуди бројне практичне предности Ове предности су приметне од најранијих примера до великих примена. Најочигледнија је читљивост: ток је написан одозго надоле без потребе за угнежђеним или ланчаним функцијама. .then() један за другим.

Још једна јака страна је одржавање кодаСа више линеарних блокова, лакше је уносити измене, издвајати делове у помоћне функције или поново користити логику. Ово директно резултира мањим бројем грешака и глађом кривом учења за нове учеснике у пројекту.

Обрада грешака са try..catch уместо вишеструких .catch() расути Помаже у централизацији логике грешака. Можете окружити неколико await са једним блоком и имплементирати доследну политику управљања грешкама, без губитка детаља о томе на којој линији се проблем појавио.

Са становишта перформанси, async/await сам по себи не чини код „бржим“, али вас може подстаћи да користите обрасце попут Promise.all() да извршавате задатке паралелно тамо где сте их претходно можда извршавали серијски. Резултат је мање укупно време чекања за крајњег корисника.

Штавише, асинхронизација/чекање је компатибилан са традиционалним обећањимаНе морате преписати цео код да бисте га усвојили. Можете комбиновати функције које га користе. .then() са другима који користе await Нема проблема, што олакшава постепено премештање пројеката.

У модерном екосистему, како у прегледачима тако и у Node.js-у, већина алата и библиотека већ се ослања на обећања и async/await. Због тога је добро учење ових концепата не опционо, већ неопходно. захтев за рад са модерним ЈаваСкриптом у професионалним пројектима.

Читав овај скуп идеја - обећања, асинхронизација/чекање, fetch, Promise.allФункција „покушај/ухвати“ и речник кључних појмова чине веома солидан оквир за писање јасан, читљив и робустан асинхрони кодСавладавање истих вам омогућава да направите модерне веб апликације које брзо реагују, добро користе мрежу и много их је лакше одржавати током времена.