logo

Пакао повратног позива у ЈаваСцрипт-у

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

У програмским језицима, пакао повратног позива генерално се односи на неефикасан начин писања кода са асинхроним позивима. Позната је и као пирамида пропасти.

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

Да бисте боље разумели пакао повратног позива у ЈаваСцрипт-у, прво разумејте повратне позиве и петље догађаја у ЈаваСцрипт-у.

Повратни позиви у ЈаваСцрипт-у

ЈаваСцрипт све сматра објектом, као што су стрингови, низови и функције. Дакле, концепт повратног позива нам омогућава да проследимо функцију као аргумент другој функцији. Функција повратног позива ће прво завршити извршење, а родитељска функција ће се извршити касније.

Функције повратног позива се извршавају асинхроно и дозвољавају коду да настави да ради без чекања да се заврши асинхрони задатак. Када се комбинује више асинхроних задатака, а сваки задатак зависи од претходног задатка, структура кода постаје компликована.

Хајде да разумемо употребу и важност повратних позива. Претпоставимо за пример да имамо функцију која узима три параметра, један низ и два броја. Желимо неки излаз заснован на тексту стринга са више услова.

Размотрите следећи пример:

 function expectedResult(action, x, y){ if(action === 'add'){ return x+y }else if(action === 'subtract'){ return x-y } } console.log(expectedResult('add',20,10)) console.log(expectedResult('subtract',30,10)) 

Излаз:

 30 20 

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

Дакле, можемо преписати код на бољи начин на следећи начин:

 function add(x,y){ return x+y } function subtract(x,y){ return x-y } function expectedResult(callBack, x, y){ return callBack(x,y) } console.log(expectedResult(add, 20, 10)) console.log(expectedResult(subtract, 30, 10)) 

Излаз:

 30 20 

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

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

Да бисмо то боље разумели, требало би да разумемо ЈаваСцрипт-ов пролаз по вредности и пролаз по референци.

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

Пасс би референце прослеђује референтну адресу ентитета, као што се функција може узети као аргумент. Дакле, ако се вредност унутар те функције промени, то ће променити оригиналну вредност, која је доступна ван функције.

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

јава сортирање низа

У ЈаваСцрипт-у аддЕвентЛистенер ослушкује догађаје као што су клик, прелазак миша и излазак миша и узима други аргумент као функцију која ће се извршити када се догађај покрене. Ова функција се користи концептом пасс би референце и прослеђена користећи без заграда.

Размотрите пример у наставку; у овом примеру смо проследили функцију греет као аргумент у аддЕвентЛистенер као функцију повратног позива. Биће позван када се покрене догађај клика:

Тест.хтмл:

 Javascript Callback Example <h3>Javascript Callback</h3> Click Here to Console const button = document.getElementById(&apos;btn&apos;); const greet=()=&gt;{ console.log(&apos;Hello, How are you?&apos;) } button.addEventListener(&apos;click&apos;, greet) 

Излаз:

Пакао повратног позива у ЈаваСцрипт-у

У горњем примеру, проследили смо греет функцију као аргумент у аддЕвентЛистенер као функцију повратног позива. Биће позван када се покрене догађај клика.

Слично томе, филтер је такође пример функције повратног позива. Ако користимо филтер за понављање низа, он ће узети другу функцију повратног позива као аргумент за обраду података низа. Размотрите пример у наставку; у овом примеру користимо функцију ларге за штампање броја већег од 5 у низу. Користимо исГреатер функцију као функцију повратног позива у методу филтера.

 const arr = [3,10,6,7] const isGreater = num =&gt; num &gt; 5 console.log(arr.filter(isGreater)) 

Излаз:

 [ 10, 6, 7 ] 

Горњи пример показује да се функција већа користи као функција повратног позива у методи филтера.

Да бисмо боље разумели повратне позиве, петље догађаја у ЈаваСцрипт-у, хајде да разговарамо о синхроном и асинхроном ЈаваСцрипт-у:

Синхрони ЈаваСцрипт

Хајде да разумемо које су карактеристике синхроног програмског језика. Синхроно програмирање има следеће карактеристике:

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

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

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

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

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

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

Али када људи говоре о ЈаваСцрипт-у, увек је био збуњујући одговор да ли је синхрони или асинхрони.

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

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

Првенствено, ЈаваСцрипт се сматра синхроним са једним навојем и блокирајућим по природи. Али користећи неколико приступа, можемо учинити да ради асинхроно на основу различитих сценарија.

Сада, хајде да разумемо асинхрони ЈаваСцрипт.

Асинхрони ЈаваСцрипт

Асинхрони програмски језик се фокусира на побољшање перформанси апликације. Повратни позиви се могу користити у таквим сценаријима. Можемо анализирати асинхроно понашање ЈаваСцрипт-а на следећем примеру:

 function greet(){ console.log(&apos;greet after 1 second&apos;) } setTimeout(greet, 1000) 

Из горњег примера, функција сетТимеоут узима повратни позив и време у милисекундама као аргументе. Повратни позив се позива након наведеног времена (овде 1с). Укратко, функција ће чекати 1с за своје извршење. Сада погледајте код у наставку:

 function greet(){ console.log(&apos;greet after 1 second&apos;) } setTimeout(greet, 1000) console.log(&apos;first&apos;) console.log(&apos;Second&apos;) 

Излаз:

 first Second greet after 1 second 

Из горњег кода, поруке дневника након сетТимеоут-а ће се прво извршити док тајмер прође. Дакле, резултат је једна секунда, а затим поздравна порука након временског интервала од 1 секунде.

У ЈаваСцрипт-у, сетТимеоут је асинхрона функција. Кад год позовемо функцију сетТимеоут, она региструје функцију повратног позива (греет у овом случају) која ће се извршити након наведеног кашњења. Међутим, то не блокира извршавање наредног кода.

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

У међувремену, петља догађаја у ЈаваСцрипт-у рукује асинхроним задацима. У овом случају, он чека да прође наведено кашњење (1 секунда) и након истека тог времена преузима функцију повратног позива (греет) и извршава је.

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

Морамо да разумемо стек позива и ред повратних позива да бисмо обрадили асинхроне догађаје у ЈаваСцрипт-у.

Размотрите слику испод:

Пакао повратног позива у ЈаваСцрипт-у

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

Меморија гомиле је одговорна за додељивање меморије за објекте и функције у време извођења кад год су они потребни.

Сада, наши претраживачи се састоје од неколико веб АПИ-ја као што су ДОМ, сетТимеоут, конзола, дохват, итд., а машина може да приступи овим АПИ-јима користећи глобални објекат прозора. У следећем кораку, неке петље догађаја играју улогу чувара врата који бира захтеве функције унутар реда за повратни позив и гура их у стек. Ове функције, као што је сетТимеоут, захтевају одређено време чекања.

Вратимо се сада на наш пример, функцију сетТимеоут; када се наиђе на функцију, тајмер се региструје у реду за повратни позив. Након тога, остатак кода се гура у стек позива и извршава се када функција достигне ограничење тајмера, истекне, а ред повратног позива гура функцију повратног позива, која има наведену логику и регистрована је у функцији временског ограничења. . Дакле, биће извршено након наведеног времена.

Сценарији пакла повратног позива

Сада смо разговарали о повратним позивима, синхроним, асинхроним и другим релевантним темама за пакао повратног позива. Хајде да разумемо шта је пакао повратног позива у ЈаваСцрипт-у.

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

јава константа

Пакао повратног позива отежава разумевање и одржавање кода. Ову ситуацију углавном можемо видети док радимо у чвору ЈС. На пример, размотрите следећи пример:

 getArticlesData(20, (articles) =&gt; { console.log(&apos;article lists&apos;, articles); getUserData(article.username, (name) =&gt; { console.log(name); getAddress(name, (item) =&gt; { console.log(item); //This goes on and on... } }) 

У горњем примеру, гетУсерДата узима корисничко име које зависи од листе чланака или га треба издвојити гетАртицлес одговор који се налази унутар чланка. гетАддресс такође има сличну зависност, која зависи од одговора гетУсерДата. Ова ситуација се зове пакао повратног позива.

Унутрашњи рад пакла повратног позива може се разумети на следећем примеру:

Хајде да схватимо да треба да извршимо задатак А. Да бисмо извршили задатак, потребни су нам подаци из задатка Б. Слично; имамо различите задатке који зависе један од другог и извршавају се асинхроно. Дакле, креира серију функција повратног позива.

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

ЈаваСцрипт обећава

У ЈаваСцрипт-у, обећања су уведена у ЕС6. То је предмет са синтаксичком превлаком. Због свог асинхроног понашања, то је алтернативни начин да се избегне писање повратних позива за асинхроне операције. Данас се веб АПИ-ји попут фетцх() имплементирају користећи обећавајуће, што пружа ефикасан начин за приступ подацима са сервера. Такође је побољшао читљивост кода и представља начин да се избегне писање угнежђених повратних позива.

Обећања у стварном животу изражавају поверење између две или више особа и уверавање да ће се одређена ствар сигурно догодити. У ЈаваСцрипт-у, Промисе је објекат који обезбеђује производњу једне вредности у будућности (када је то потребно). Промисе у ЈаваСцрипт-у се користи за управљање и решавање асинхроних операција.

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

Генерално, обећања имају следећа три стања:

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

Синтакса за обећања:

 let newPromise = new Promise(function(resolve, reject) { // asynchronous call is made //Resolve or reject the data }); 

Испод је пример писања обећања:

Ово је пример писања обећања.

 function getArticleData(id) { return new Promise((resolve, reject) =&gt; { setTimeout(() =&gt; { console.log(&apos;Fetching data....&apos;); resolve({ id: id, name: &apos;derik&apos; }); }, 5000); }); } getArticleData(&apos;10&apos;).then(res=&gt; console.log(res)) 

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

Асинц/Аваит у ЈаваСцрипт-у

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

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

Не можемо да користимо Асинц/Аваит са нормалним функцијама повратног позива. Да бисмо је користили, морамо да учинимо функцију асинхроном тако што ћемо написати асинц кључну реч испред кључне речи функције. Међутим, интерно такође користи уланчавање.

Испод је пример Асинц/Аваит:

 async function displayData() { try { const articleData = await getArticle(10); const placeData = await getPlaces(article.name); const cityData = await getCity(place) console.log(city); } catch (err) { console.log(&apos;Error: &apos;, err.message); } } displayData(); 

Да бисте користили Асинц/Аваит, функција мора бити специфицирана са кључном речи асинц, а кључна реч аваит треба да буде написана унутар функције. Асинхронизација ће зауставити своје извршавање док се обећање не реши или одбије. Биће настављен када се обећање испуни. Када се реши, вредност израза чекања биће сачувана у променљивој која га држи.

резиме:

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

Закључак:

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

Да бисте боље разумели пакао повратног позива у ЈаваСцрипт-у.

ЈаваСцрипт све сматра објектом, као што су стрингови, низови и функције. Дакле, концепт повратног позива нам омогућава да проследимо функцију као аргумент другој функцији. Функција повратног позива ће прво завршити извршење, а родитељска функција ће се извршити касније.

Функције повратног позива се извршавају асинхроно и дозвољавају коду да настави да ради без чекања да се заврши асинхрони задатак.