Tiyeni tiwone Async/Await mu JavaScript pogwiritsa ntchito zitsanzo

Wolemba nkhaniyi akuwunika zitsanzo za Async/Await mu JavaScript. Ponseponse, Async/Await ndi njira yabwino yolembera ma code asynchronous. Izi zisanachitike, code yotereyi idalembedwa pogwiritsa ntchito ma callbacks ndi malonjezo. Wolemba nkhani yoyambirira amawulula zabwino za Async/Await posanthula zitsanzo zosiyanasiyana.

Tikukukumbutsani: kwa owerenga onse a Habr - kuchotsera ma ruble 10 polembetsa maphunziro aliwonse a Skillbox pogwiritsa ntchito nambala yotsatsira ya Habr.

Skillbox imalimbikitsa: Maphunziro aulere pa intaneti "Wopanga Java".

callback

Callback ndi ntchito yomwe kuyimba kwake kumachedwetsedwa mpaka kalekale. M'mbuyomu, ma callbacks ankagwiritsidwa ntchito m'madera a code komwe zotsatira zake sizinkapezeka nthawi yomweyo.

Nachi chitsanzo cha kuwerenga mosasunthika fayilo mu Node.js:

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

Mavuto amadza mukafunika kuchita maopaleshoni angapo nthawi imodzi. Tiyeni tiyerekeze izi: pempho laperekedwa ku database ya Arfat, muyenera kuwerenga mbiri yake_img_url ndikutsitsa chithunzi kuchokera pa seva ya someserver.com.
Tikatsitsa, timatembenuza chithunzicho kukhala mtundu wina, mwachitsanzo kuchokera ku PNG kupita ku JPEG. Ngati kutembenuka kunali kopambana, kalata imatumizidwa ku imelo ya wogwiritsa ntchito. Kenako, chidziwitso chokhudza chochitikacho chimalowetsedwa mufayilo ya transformations.log, kuwonetsa tsiku.

Ndikoyenera kulabadira kuphatikizika kwa ma callbacks ndi kuchuluka kwa }) mu gawo lomaliza la code. Imatchedwa Callback Hell kapena Pyramid of Doom.

Zoyipa za njirayi ndizodziwikiratu:

  • Khodi iyi ndi yovuta kuwerenga.
  • Zimakhalanso zovuta kuthana ndi zolakwika, zomwe nthawi zambiri zimabweretsa kutsika kwa code.

Pofuna kuthetsa vutoli, malonjezo anawonjezeredwa ku JavaScript. Amakulolani kuti musinthe zisa zakuya za callbacks ndi mawu akuti .ndiye.

Mbali yabwino ya malonjezo ndi yakuti amapangitsa kuti code ikhale yabwino kwambiri, kuchokera pamwamba mpaka pansi osati kuchokera kumanzere kupita kumanja. Komabe, malonjezo amakhalanso ndi zovuta zake:

  • Muyenera kuwonjezera zambiri .ndiye.
  • M'malo moyesera/kugwira, .catch imagwiritsidwa ntchito kuthana ndi zolakwika zonse.
  • Kugwira ntchito ndi malonjezo angapo mkati mwa loop imodzi sikophweka nthawi zonse; nthawi zina, zimasokoneza code.

Nali vuto lomwe liwonetsa tanthauzo la mfundo yomaliza.

Tiyerekeze kuti tili ndi loop yomwe imasindikiza manambala angapo kuchokera pa 0 mpaka 10 pafupipafupi (masekondi 0-n). Pogwiritsa ntchito malonjezo, muyenera kusintha loop kuti manambala asindikizidwe motsatizana kuyambira 0 mpaka 10. Choncho, ngati zimatenga masekondi 6 kuti musindikize zero ndi 2 masekondi kuti musindikize imodzi, zero iyenera kusindikizidwa poyamba, ndiyeno. kuwerengera kusindikiza kudzayamba.

Ndipo ndithudi, sitigwiritsa ntchito Async/Await kapena .sort kuthetsa vutoli. Chitsanzo yankho lili kumapeto.

Async ntchito

Kuwonjezera kwa ntchito za async mu ES2017 (ES8) kunapangitsa kuti ntchito yogwira ntchito ndi malonjezo ikhale yosavuta. Ndikuwona kuti ntchito za async zimagwira ntchito "pamwamba" pamalonjezo. Ntchitozi siziyimira malingaliro osiyanasiyana. Ntchito za Async zimapangidwira ngati njira ina yogwiritsira ntchito malonjezo.

Async/Await imapangitsa kuti pakhale zotheka kukonza ntchito ndi kachidindo kosasinthika m'njira yofananira.

Choncho, kudziwa malonjezo kumapangitsa kuti zikhale zosavuta kumvetsa mfundo za Async/Await.

malembedwe

Nthawi zambiri imakhala ndi mawu osakira awiri: async ndikuyembekezera. Mawu oyamba amasintha ntchitoyi kukhala yosasinthika. Zochita zoterezi zimalola kugwiritsa ntchito kuyembekezera. Mulimonsemo, kugwiritsa ntchito izi kumabweretsa cholakwika.

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

Async imayikidwa kumayambiriro kwenikweni kwa chilengezo cha ntchito, ndipo ngati ntchito ya muvi, pakati pa "="" chizindikiro ndi makolo.

Ntchitozi zitha kuyikidwa mu chinthu ngati njira kapena kugwiritsidwa ntchito polengeza kalasi.

// 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! Ndikoyenera kukumbukira kuti omanga kalasi ndi ma getters/setter sangakhale asynchronous.

Semantics ndi malamulo akupha

Ntchito za Async ndizofanana ndi ntchito za JS, koma pali zosiyana.

Chifukwa chake, ntchito za async nthawi zonse zimabwezera malonjezo:

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

Makamaka, fn imabwezera chingwe moni. Chabwino, popeza iyi ndi ntchito yofanana, mtengo wa chingwe umakutidwa ndi lonjezo pogwiritsa ntchito womanga.

Nayi njira ina yopanda Async:

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

Pachifukwa ichi, lonjezolo likubwezeredwa "pamanja". Ntchito ya asynchronous nthawi zonse imakutidwa ndi lonjezo latsopano.

Ngati mtengo wobwezera ndi wachikale, ntchito ya async imabwezeretsa mtengowo poukulunga mu lonjezo. Ngati mtengo wobwezera ndi chinthu cholonjeza, chigamulo chake chimabwezeredwa mu lonjezo latsopano.

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

Koma chimachitika ndi chiyani ngati pali cholakwika mkati mwa ntchito ya asynchronous?

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

Ngati sichinasinthidwe, foo() ibweza lonjezo ndikukanidwa. Zikatero, Promise.reject yomwe ili ndi cholakwika ibwezedwa m'malo mwa Promise.resolve.

Ntchito za Async nthawi zonse zimatulutsa lonjezo, mosasamala kanthu za zomwe zabwezedwa.

Ntchito za Asynchronous zimayima nthawi zonse.

Kudikira kumakhudza mawu. Chifukwa chake, ngati mawuwo ndi lonjezo, ntchito ya async imayimitsidwa mpaka lonjezolo litakwaniritsidwa. Ngati mawuwa sali lonjezo, amasinthidwa kukhala lonjezo kudzera pa Promise.resolve ndiyeno kumalizidwa.

// 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);

Ndipo apa pali kufotokozera momwe fn ntchito imagwirira ntchito.

  • Atatha kuyitcha, mzere woyamba umasinthidwa kuchokera ku const a = wait 9; mu const a = ait Promise.resolve(9);.
  • Mukamagwiritsa ntchito Kudikira, ntchitoyo imayimitsidwa mpaka a itapeza mtengo wake (pakali pano ndi 9).
  • delayAndGetRandom(1000) imayimitsa kaye ntchito ya fn mpaka itamaliza yokha (pambuyo pa sekondi imodzi). Izi zimayimitsa ntchito ya fn kwa sekondi imodzi.
  • delayAndGetRandom(1000) kudzera kusolve imabweretsa mtengo wachisawawa, womwe umaperekedwa ku b.
  • Chabwino, vuto la variable c ndi lofanana ndi la variable a. Pambuyo pake, chilichonse chimayima kamphindi, koma tsopano kuchedwaAndGetRandom(1000) sikubweza chilichonse chifukwa sizofunikira.
  • Zotsatira zake, zikhalidwe zimawerengedwa pogwiritsa ntchito formula a + b * c. Zotsatira zake zimakutidwa ndi lonjezo pogwiritsa ntchito Promise.resolve ndikubwezeredwa ndi ntchitoyi.

Kuyimitsa uku kungakhale ngati kukumbukira majenereta mu ES6, koma pali china chake zifukwa zanu.

Kuthetsa vuto

Chabwino, tsopano tiyeni tione njira yothetsera vuto tatchulazi.

The finishMyTask ntchito imagwiritsa ntchito Await kudikirira zotsatira za ntchito monga queryDatabase, sendEmail, logTaskInFile, ndi ena. Mukayerekezera yankho limeneli ndi limene malonjezo anagwiritsidwa ntchito, kufanana kwake kudzaonekera. Komabe, mtundu wa Async/Await umathandizira kwambiri zovuta zonse. Pamenepa, palibe chiwerengero chachikulu cha ma callbacks ndi maunyolo monga .then/.catch.

Pano pali yankho ndi linanena bungwe manambala, pali njira ziwiri.

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);
    });
  });
};

Ndipo apa pali yankho ntchito async ntchito.

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

Kukonza zolakwika

Zolakwa zosasamalidwa zimakutidwa ndi lonjezo lokanidwa. Komabe, ntchito za async zitha kugwiritsa ntchito kuyesa / kugwira kuthana ndi zolakwika mogwirizana.

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() ndi ntchito yofananira yomwe imapambana ("nambala yabwino") kapena kulephera ndi cholakwika ("Pepani, nambala yayikulu kwambiri").

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

Popeza chitsanzo pamwambapa chikuyembekeza kuti canRejectOrReturn achite, kulephera kwake kudzapangitsa kuti chipikacho chigwire. Zotsatira zake, ntchito foo idzatha ndi zosadziwika (pamene palibe chomwe chidzabwezedwe mu chipika choyesera) kapena ndi cholakwika chogwidwa. Zotsatira zake, ntchitoyi silephera chifukwa kuyesa / kugwira kumagwira ntchito foo palokha.

Nachi chitsanzo china:

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

Ndikoyenera kulabadira kuti mu chitsanzo, canRejectOrReturn wabwezedwa kuchokera foo. Foo pankhaniyi mwina atha ndi nambala yabwino kapena abweza Cholakwika (β€œPepani, nambala yayikulu kwambiri”). Chophimbacho sichidzachitidwa konse.

Vuto ndiloti foo amabwezera lonjezo lomwe laperekedwa kuchokera ku canRejectOrReturn. Chifukwa chake yankho la foo limakhala yankho la canRejectOrReturn. Pankhaniyi, code idzakhala ndi mizere iwiri yokha:

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

Izi ndi zomwe zimachitika mukamagwiritsa ntchito await ndikubwerera limodzi:

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

Mu code ili pamwambapa, foo idzatuluka bwino ndi nambala yabwino komanso zolakwika zomwe zagwidwa. Sipadzakhala zokana pano. Koma foo adzabwerera ndi canRejectOrReturn, osati ndi undefined. Tiyeni tiwonetsetse izi pochotsa mzere wobwerera woyembekezera canRejectOrReturn():

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

Zolakwa zofala ndi misampha

Nthawi zina, kugwiritsa ntchito Async/Await kungayambitse zolakwika.

Kuyiwalika kuyembekezera

Izi zimachitika nthawi zambiri - mawu ofunikira amaiwalika asanalonjeze:

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

Monga mukuonera, palibe kuyembekezera kapena kubwerera mu code. Chifukwa chake foo nthawi zonse amatuluka ndi undefined popanda kuchedwa 1 sekondi. Koma lonjezolo lidzakwaniritsidwa. Ngati iponya cholakwika kapena kukana, ndiye UnhandledPromiseRejectionWarning idzayitanidwa.

Ntchito za Async mu Callbacks

Ntchito za Async zimagwiritsidwa ntchito nthawi zambiri mu .map kapena .sefa ngati ma callbacks. Chitsanzo ndi ntchito ya fetchPublicReposCount(username), yomwe imabweza kuchuluka kwa nkhokwe zotseguka pa GitHub. Tiyerekeze kuti pali ogwiritsa ntchito atatu omwe timafunikira ma metric. Nayi code ya ntchitoyi:

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'];
}

Tikufuna maakaunti a ArfatSalman, octocat, norvig. Pankhaniyi timachita:

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

Ndikoyenera kutchera khutu ku Await mu .map callback. Pano kuwerengera ndi malonjezo angapo, ndipo .map ndi kuyitananso mosadziwika kwa wogwiritsa ntchito aliyense.

Kugwiritsa ntchito mopitilira muyeso kudikirira

Tiyeni titenge code iyi mwachitsanzo:

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;
}

Pano nambala ya repo imayikidwa mu chiwerengero chowerengera, ndiye nambala iyi imawonjezedwa kumagulu owerengera. Vuto la code ndiloti mpaka deta ya wogwiritsa ntchito yoyamba ifike kuchokera ku seva, ogwiritsa ntchito onse omwe akutsatira adzakhala mu mode standby. Chifukwa chake, wogwiritsa ntchito m'modzi yekha amakonzedwa panthawi imodzi.

Ngati, mwachitsanzo, zimatengera pafupifupi 300 ms kukonza wogwiritsa ntchito m'modzi, ndiye kwa onse ogwiritsa ntchito ili kale sekondi; nthawi yomwe imagwiritsidwa ntchito motsatana imadalira kuchuluka kwa ogwiritsa ntchito. Koma popeza kupeza kuchuluka kwa repo sikudalirana, njirazo zitha kufananizidwa. Izi zimafuna kugwira ntchito ndi .map ndi Promise.all:

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

Promise.all amalandira malonjezo ochuluka monga kulowetsedwa ndikubweza lonjezo. Chotsatiracho, pambuyo poti malonjezano onse pamndandandawo atha kapena kukanidwa koyamba, atha. Zitha kuchitika kuti onse samayamba nthawi imodzi - kuti muwonetsetse kuti mukuyamba nthawi imodzi, mutha kugwiritsa ntchito mapu.

Pomaliza

Ntchito za Async zikukhala zofunika kwambiri pachitukuko. Chabwino, kuti mugwiritse ntchito mosinthika ntchito za async ndizoyenera kugwiritsa ntchito Async Iterators. Wopanga JavaScript ayenera kudziwa bwino izi.

Skillbox imalimbikitsa:

Source: www.habr.com

Kuwonjezera ndemanga