Aynu eegno Async/Await ee JavaScript anagoo adeegsanayna tusaalooyin

Qoraaga maqaalku wuxuu eegayaa tusaalooyinka Async/Await ee JavaScript. Guud ahaan, Async/Await waa hab ku habboon oo lagu qoro koodka asynchronous. Kahor inta aan muuqaalkani soo bixin, koodka noocaas ah ayaa la qoray iyadoo la isticmaalayo dib-u-soo-celin iyo ballan-qaadyo. Qoraaga maqaalka asalka ah wuxuu muujinayaa faa'iidooyinka Async/Await isagoo falanqaynaya tusaalooyin kala duwan.

Waxaan xusuusineynaa: dhammaan akhristayaasha "Habr" - qiimo dhimis ah 10 rubles marka la qorayo koorso kasta oo Skillbox ah iyadoo la adeegsanayo koodhka xayeysiinta "Habr".

Skillbox waxay ku talinaysaa: Koorso online ah oo waxbarasho "horumariyaha Java".

callback

Dib-u-soo-warciddu waa hawl wicitaankeedu dib u dhacay si aan xad lahayn. Markii hore, dib-u-warcelinta ayaa lagu isticmaali jiray meelaha koodka halkaas oo natiijada isla markiiba aan la heli karin.

Waa kuwan tusaale ku saabsan akhrinta faylka Node.js:

fs.readFile(__filename, 'utf-8', (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
});

Dhibaatooyinku waxay soo baxaan marka aad u baahato inaad sameyso dhawr hawlgal oo isku mid ah hal mar. Aynu qiyaaso dhacdadan: codsi ayaa loo gudbiyay kaydka xogta isticmaalaha Arfat, waxaad u baahan tahay inaad akhrido profile_img_url goobta ay ku leedahay oo aad ka soo dejiso sawir server-ka someserver.com.
Ka dib markii la soo dejiyo, waxaan u beddelnaa sawirka qaab kale, tusaale ahaan PNG ilaa JPEG. Haddii beddelidda lagu guulaystey, warqad ayaa loo diraa iimaylka isticmaalaha. Marka xigta, macluumaadka ku saabsan dhacdada ayaa la geliyaa faylka transformations.log, oo tilmaamaya taariikhda.

Waxaa habboon in fiiro gaar ah loo yeesho isku dhafka dib-u-soo-celinta iyo tirada badan ee }) ee qaybta ugu dambeysa ee koodka. Waxaa loo yaqaan Callback Hell ama Ahraamta Doomka.

Faa'iido darrada habkan waa caddahay:

  • Koodhkan waa ay adagtahay in la akhriyo.
  • Sidoo kale way adag tahay in la xalliyo khaladaadka, taas oo inta badan keenta tayada koodka.

Si loo xalliyo dhibaatadan, balamo ayaa lagu daray JavaScript. Waxay kuu oggolaanayaan inaad ku beddesho buulka qoto dheer ee dib-u-soo-celinta ereyga .markaa.

Dhinaca togan ee ballan-qaadyadu waa inay ka dhigaan koodhka si aad u wanaagsan oo la akhriyi karo, min sare ilaa hoos halkii laga bilaabi lahaa bidix ilaa midig. Si kastaba ha ahaatee, ballanqaadyadu sidoo kale waxay leeyihiin dhibaatooyinkooda:

  • Waxaad u baahan tahay inaad wax badan ku darto .markaas.
  • Halkii aad isku dayi lahayd/qabsan lahayd, .catch waxa loo isticmaalaa in lagu xakameeyo dhammaan khaladaadka.
  • Ku shaqeynta balamo badan oo hal wareeg ah mar walba ma fududa; xaaladaha qaarkood, waxay adkeeyaan koodka.

Halkan waxaa ah dhibaato muujin doonta macnaha qodobka u dambeeya.

Ka soo qaad in aanu haysano loop-ka daabacaadda taxanaha tirooyinka laga bilaabo 0 ilaa 10 wakhtiyo aan kala sooc lahayn (0–n seconds). Adigoo isticmaalaya balamaha, waxaad u baahan tahay inaad beddesho wareeggan si nambarada loogu daabaco isku xigxiga laga bilaabo 0 ilaa 10. Haddaba, haddii ay qaadato 6 ilbiriqsi in la daabaco eber iyo 2 ilbiriqsi si loo daabaco mid, eber waa in marka hore la daabacaa, ka dibna tirinta daabacaada midda ayaa bilaaban doonta.

Dabcan, ma isticmaalno Async/Await ama .sooc si loo xalliyo dhibaatadan. Tusaale ahaan xalku waa dhamaadka.

Hawlaha Async

Ku darida hawlaha async ee ES2017 (ES8) waxay fududaysay hawsha ku shaqaynta ballanqaadyada. Waxaan ogsoonahay in hawlaha async ay ka shaqeeyaan "sare" ballanqaadyada. Hawlahani ma matalaan fikrado kala duwan oo tayo leh. Hawlaha Async waxaa loogu talagalay beddelka koodka isticmaala ballanqaadyada.

Async/Await waxa ay suurtogal ka dhigtaa in lagu habeeyo shaqada koodka asynchronous ee qaab isku mid ah.

Sidaa darteed, ogaanshaha ballanqaadyadu waxay sahlaysaa in la fahmo mabaadi'da Async/Await.

Saan

Caadi ahaan waxay ka kooban tahay laba erey oo muhiim ah: async iyo sug. Erayga ugu horreeya waxa uu shaqada u beddelaa asynchronous. Hawlaha noocan oo kale ah waxay ogolaadaan isticmaalka sugitaanka. Xaalad kasta oo kale, isticmaalka shaqadan waxay dhalin doontaa qalad.

// With function declaration
 
async function myFn() {
  // await ...
}
 
// With arrow function
 
const myFn = async () => {
  // await ...
}
 
function myFn() {
  // await fn(); (Syntax Error since no async)
}
 

Async waxaa la geliyaa bilowga hore ee cadeynta shaqada, iyo xaalada falaadha, inta u dhaxaysa calaamadda "=" iyo qawladaha.

Hawlahan waxaa loo gelin karaa shay qaab ahaan ama waxaa loo isticmaali karaa caddaynta fasalka.

// As an object's method
 
const obj = {
  async getName() {
    return fetch('https://www.example.com');
  }
}
 
// In a class
 
class Obj {
  async getResource() {
    return fetch('https://www.example.com');
  }
}

NB! Waxaa mudan in la xasuusto in wax-dhisayaasha fasalka iyo kuwa heshiiyeyaashu aanay noqon karin kuwo isku mid ah.

Semantics iyo xeerarka fulinta

Hawlaha Async waxay asal ahaan la mid yihiin shaqooyinka caadiga ah ee JS, laakiin waxaa jira waxyaabo ka reeban.

Markaa, hawlaha async had iyo jeer waxay soo celiyaan ballanqaadyada:

async function fn() {
  return 'hello';
}
fn().then(console.log)
// hello

Gaar ahaan, fn waxay soo celisaa xadhigga hello. Hagaag, maadaama tani ay tahay hawl aan la wada socon, qiimaha xadhiggu wuxuu ku duudduubay ballan iyadoo la isticmaalayo dhisme.

Halkan waxaa ah naqshad kale oo aan lahayn Async:

function fn() {
  return Promise.resolve('hello');
}
 
fn().then(console.log);
// hello

Xaaladdan oo kale, ballanta waxaa lagu soo celiyaa "gacan". Shaqada asynchronous waxay had iyo jeer ku duuduubtaa ballan cusub.

Haddii qiimaha soo celinta uu yahay mid hore, shaqada async waxay soo celisaa qiimaha adoo ku duubaya ballan. Haddii qiimaha soo celinta uu yahay shay ballan, xalintiisa waxaa lagu soo celiyaa ballan cusub.

const p = Promise.resolve('hello')
p instanceof Promise;
// true
 
Promise.resolve(p) === p;
// true
 

Laakiin maxaa dhacaya haddii uu khalad ka jiro gudaha shaqada asynchronous?

async function foo() {
  throw Error('bar');
}
 
foo().catch(console.log);

Haddii aan la farsamayn, foo() waxay soo celin doontaa ballan diidmo. Xaaladdan oo kale, Ballanqaad.diidmo ay ku jiraan khalad ayaa la soo celin doonaa halkii Ballanqaad.xalin lahaa.

Hawlaha Async waxay had iyo jeer soo saaraan ballan, iyada oo aan loo eegin waxa la soo celiyo.

Hawlaha aan la isku lahayn ayaa hakad ku jira sugitaan kasta .

Suggu waxay saamaysaa tibaaxaha Sidaa darteed, haddii tibaaxuhu yahay ballan, shaqada async waa la hakiyaa ilaa ballanqaadka la fuliyo. Haddii tibaaxuhu aanu ahayn ballan, waxa loo rogaa ballan-qaad iyada oo loo marayo Ballanqaad.xali ka dibna la dhammaystiro.

// utility function to cause delay
// and get random value
 
const delayAndGetRandom = (ms) => {
  return new Promise(resolve => setTimeout(
    () => {
      const val = Math.trunc(Math.random() * 100);
      resolve(val);
    }, ms
  ));
};
 
async function fn() {
  const a = await 9;
  const b = await delayAndGetRandom(1000);
  const c = await 5;
  await delayAndGetRandom(1000);
 
  return a + b * c;
}
 
// Execute fn
fn().then(console.log);

Oo halkan waa sharaxaad ku saabsan sida shaqada fn u shaqeyso.

  • Ka dib marka la waco, xariiqda koowaad waxaa laga rogaa const a = sug 9; in const a = sugi Ballanqaad.xalin(9);.
  • Kadib isticmaalka Await, fulinta shaqadu waa la hakiyay ilaa a uu helayo qiimaheeda (xaaladda hadda jirta waa 9).
  • delayAndGetRandom(1000) waxay hakisaa fulinta fn function ilaa ay ka dhammayso lafteeda (1 sekan ka dib). Tani waxay si wax ku ool ah u joojisaa shaqada fn ilaa 1 ilbiriqsi.
  • delayAndGetRandom(1000) iyada oo loo marayo xallinta waxay soo celisaa qiime aan toos ahayn, kaas oo markaa loo qoondeeyay doorsoomaha b.
  • Hagaag, kiiska variable c wuxuu la mid yahay kiis doorsoome a. Intaa ka dib, wax walbaa waxay istaagaan ilbidhiqsi, laakiin hadda daahitaankaAndGetRandom(1000) waxba kuma soo celinayaan sababtoo ah looma baahna.
  • Natiijo ahaan, qiyamka waxaa lagu xisaabiyaa iyadoo la isticmaalayo qaacidada a + b * c. Natiijadu waxay ku duudduuban ballanqaad iyadoo la adeegsanayo Promise.resolve oo lagu soo celiyay shaqada.

hakadyadani waxa laga yaabaa inay dib u xasuusiyaan koronto-dhaliyeyaasha ES6, laakiin wax baa ku jira sababahaaga.

Xalinta dhibaatada

Hagaag, hadda aan eegno xalka dhibaatada kor ku xusan.

DhamaystirkaMyTask waxay isticmaashaa Sug si ay u sugto natiijooyinka hawlgallada sida queryDatabase, dirEmail, logTaskInFile, iyo kuwa kale. Haddii aad is barbardhigto xalkan iyo kan ballan-qaadyada la adeegsaday, waxa ay isu egyihiin ayaa muuqanaya. Si kastaba ha ahaatee, nooca Async/Await ayaa si weyn u fududeynaya dhammaan kakanaanta isku midka ah. Xaaladdan oo kale, ma jiraan tiro badan oo dib-u-soo-celin iyo silsilado ah sida .kadib/.qabso.

Halkan waxaa ah xalka soo saarista tirooyinka, waxaa jira laba ikhtiyaar.

const wait = (i, ms) => new Promise(resolve => setTimeout(() => resolve(i), ms));
 
// Implementation One (Using for-loop)
const printNumbers = () => new Promise((resolve) => {
  let pr = Promise.resolve(0);
  for (let i = 1; i <= 10; i += 1) {
    pr = pr.then((val) => {
      console.log(val);
      return wait(i, Math.random() * 1000);
    });
  }
  resolve(pr);
});
 
// Implementation Two (Using Recursion)
 
const printNumbersRecursive = () => {
  return Promise.resolve(0).then(function processNextPromise(i) {
 
    if (i === 10) {
      return undefined;
    }
 
    return wait(i, Math.random() * 1000).then((val) => {
      console.log(val);
      return processNextPromise(i + 1);
    });
  });
};

Oo halkan waa xalka iyadoo la adeegsanayo hawlaha async.

async function printNumbersUsingAsync() {
  for (let i = 0; i < 10; i++) {
    await wait(i, Math.random() * 1000);
    console.log(i);
  }
}

Khalad habaynta

Khaladaadka aan la maarayn waxay ku duudduubeen ballan la diiday. Si kastaba ha ahaatee, hawlaha async waxay isticmaali karaan isku day/qabasho si ay si isku mid ah u xalliyaan khaladaadka.

async function canRejectOrReturn() {
  // wait one second
  await new Promise(res => setTimeout(res, 1000));
 
// Reject with ~50% probability
  if (Math.random() > 0.5) {
    throw new Error('Sorry, number too big.')
  }
 
return 'perfect number';
}

canRejectOrReturn() waa hawl aan isku mid ahayn oo ama ku guulaysata ("lambarka saxda ah") ama ku fashilma khalad ("Waan ka xunahay, nambarku aad buu u weyn yahay").

async function foo() {
  try {
    await canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

Mar haddii tusaalaha sare uu filayo canRejectOrReturn inuu fuliyo, guuldarradeedu waxay keeni doontaa fulinta xannibaadda qabsashada. Natiijo ahaan, foo shaqadu waxay ku dhammaan doontaa mid aan la qeexin (marka aan waxba lagu soo celin qaybta isku dayga) ama qalad la qabtay. Natiijo ahaan, shaqadani ma fashilmi doonto sababtoo ah isku dayga/qabashadu waxay xakamaysaa shaqada foo lafteeda.

Waa kan tusaale kale:

async function foo() {
  try {
    return canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

Waxaa habboon in fiiro gaar ah loo yeesho xaqiiqda in tusaale ahaan, canRejectOrReturn laga soo celiyay foo. Foo kiiskan ama wuxuu ku dhammeeyaa nambar kaamil ah ama wuxuu soo celiyaa qalad ("Waan ka xunahay, lambarka aad u weyn"). Meesha la qabto waligeed lama fulin doono.

Dhibaatadu waa in foo ay soo celiso ballantii laga soo gudbiyay canRejectOrReturn. Markaa xalka foo wuxuu noqonayaa xalka canRejectOrReturn. Xaaladdan, koodka wuxuu ka koobnaan doonaa laba xariiq oo keliya:

try {
    const promise = canRejectOrReturn();
    return promise;
}

Waa kuwan waxa dhacaya haddii aad adeegsato sug oo aad isla soo noqotaan:

async function foo() {
  try {
    return await canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

Koodhka sare, foo waxa uu si guul leh uga bixi doonaa iyada oo labaddaba lambar qumman iyo khalad la qabto. Ma jiri doonto wax diidmo ah halkan. Laakiin foo waxa ay la soo noqon doontaa canRejectOrReturn, oo aan la qeexin. Aan hubinno tan annagoo meesha ka saarna soo celinta sugidda canRejectOrReturn() line:

try {
    const value = await canRejectOrReturn();
    return value;
}
// …

Khaladaadka caadiga ah iyo dabinnada

Xaaladaha qaarkood, isticmaalka Async/Await waxay u horseedi kartaa khaladaad.

Waa la ilaaway

Tani waxay dhacdaa marar badan - ereyga sugitaanka waa la ilaaway ballanka ka hor:

async function foo() {
  try {
    canRejectOrReturn();
  } catch (e) {
    return 'caught';
  }
}

Sida aad arki karto, ma jiro sugitaan ama soo celin koodka. Sidaa darteed foo had iyo jeer waxay ku baxdaa iyada oo aan la qeexin iyada oo aan dib loo dhigin 1 ilbiriqsi. Laakin ballankii waa la oofi doonaa. Haddii ay tuurto khalad ama diidmo, markaas UnhandledPromiseRejectionWarning ayaa la wici doonaa.

Async Functions gudaha Wicitaanka

Hawlaha Async waxaa inta badan loo adeegsadaa khariidad ama .filter sida dib-u-soo yeedhid. Tusaale ahaan shaqada fetchPublicReposCount(username), oo soo celisa tirada kaydka furan ee GitHub. Aynu nidhaahno waxaa jira saddex isticmaale oo cabbirkooda aan u baahanahay. Waa kan koodka hawshan:

const url = 'https://api.github.com/users';
 
// Utility fn to fetch repo counts
const fetchPublicReposCount = async (username) => {
  const response = await fetch(`${url}/${username}`);
  const json = await response.json();
  return json['public_repos'];
}

Waxaan u baahanahay ArfatSalman, octocat, norvig accounts. Xaaladdan oo kale waxaan sameynaa:

const users = [
  'ArfatSalman',
  'octocat',
  'norvig'
];
 
const counts = users.map(async username => {
  const count = await fetchPublicReposCount(username);
  return count;
});

Waxaa mudan in fiiro gaar ah loo yeesho Sugitaanka khariidadda dib-u-soo-celinta. Halkan waxaa lagu tiriyaa ballanqaadyo kala duwan, iyo .mapku waa soo celin qarsoodi ah oo isticmaale kasta oo cayiman ah.

Isticmaalka sugitaanka oo joogto ah

Aan tusaale u soo qaadano xeerkan:

async function fetchAllCounts(users) {
  const counts = [];
  for (let i = 0; i < users.length; i++) {
    const username = users[i];
    const count = await fetchPublicReposCount(username);
    counts.push(count);
  }
  return counts;
}

Halkan waxaa la dhigayaa lambarka repo ee doorsoomaha tirinta, ka dib nambarkan waxaa lagu darayaa habraaca tirinta. Dhibaatada koodka ayaa ah in ilaa xogta isticmaalaha ugu horreeya ay ka yimaadaan server-ka, dhammaan isticmaalayaasha ku xiga waxay ku jiri doonaan qaabka heeganka. Markaa, hal isticmaale oo keliya ayaa hal mar laga baaraandegayaa.

Haddii, tusaale ahaan, ay qaadato qiyaastii 300 ms si loo farsameeyo hal isticmaale, markaa dhammaan isticmaalayaasha waxay mar horeba u tahay ilbiriqsi; wakhtiga si toos ah loo isticmaalo waxay kuxirantahay tirada isticmaaleyaasha. Laakiin maadaama helitaanka tirada repo kuma xirna midba midka kale, geeddi-socodyada waa la barbar dhigi karaa. Tani waxay u baahan tahay ka shaqaynta .map iyo Promise.all:

async function fetchAllCounts(users) {
  const promises = users.map(async username => {
    const count = await fetchPublicReposCount(username);
    return count;
  });
  return Promise.all(promises);
}

Ballanqaadka Dambe, ka dib markii dhammaan ballamihii diyaarintu ay dhammaadaan ama diidmada koowaad, waa la dhammaystiraa. Waxaa laga yaabaa inay dhacdo in dhammaantood aysan isku mar bilaaban - si loo hubiyo in isku mar la bilaabo, waxaad isticmaali kartaa khariidadda p-map.

gunaanad

Hawlaha Async waxay noqonayaan kuwo sii kordheysa oo muhiim u ah horumarka. Hagaag, isticmaalka la qabsiga ee hawlaha async, waa inaad isticmaashaa Async Iterators. Horumariyaha JavaScript waa inuu si fiican u yaqaan tan.

Skillbox waxay ku talinaysaa:

Source: www.habr.com

Add a comment