Ngatitarisei Async/Mirira muJavaScript tichishandisa mienzaniso

Munyori wechinyorwa anoongorora mienzaniso yeAsync/Kumirira muJavaScript. Pakazara, Async/Kumirira inzira iri nyore yekunyora asynchronous kodhi. Iyi ficha isati yaoneka, kodhi yakadaro yakanyorwa uchishandisa callbacks uye zvivimbiso. Munyori wechinyorwa chepakutanga anoburitsa zvakanakira Async / Mirira nekuongorora akasiyana mienzaniso.

Tinoyeuchidza: kune vese vaverengi veHabr - a 10 ruble mutengo paunenge uchinyoresa mune chero Skillbox kosi uchishandisa iyo Habr promo kodhi.

Skillbox inokurudzira: Dzidzo yepamhepo kosi "Java developer".

callback

Callback ibasa rine kufona kunonokerwa nekusingaperi. Pakutanga, macallbacks aishandiswa munzvimbo idzodzo dzekodhi apo mhedzisiro yaisagona kuwanikwa nekukurumidza.

Heino muenzaniso weasynchronously kuverenga faira muNode.js:

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

Matambudziko anomuka kana iwe uchida kuita akati wandei asynchronous oparesheni kamwechete. Ngatimbofungidzirai mamiriro ezvinhu aya: chikumbiro chinoitwa kune Arfat mushandisi dhatabhesi, iwe unofanirwa kuverenga yayo profile_img_url ndima uye kudhawunirodha mufananidzo kubva kune someserver.com server.
Mushure mekurodha, tinoshandura chifananidzo kune imwe fomati, semuenzaniso kubva kuPNG kuenda kuJPEG. Kana shanduko yakabudirira, tsamba inotumirwa kune email yemushandisi. Tevere, ruzivo nezve chiitiko chinopinzwa mushanduro.log faira, zvichiratidza zuva.

Izvo zvakakodzera kubhadhara kune kupindirana kwecallbacks uye nhamba huru ye}) muchikamu chekupedzisira chekodhi. Inonzi Callback Hell kana Pyramid of Doom.

Kuipa kweiyi nzira kuri pachena:

  • Kodhi iyi yakaoma kuverenga.
  • Izvo zvakare zvakaoma kubata zvikanganiso, izvo zvinowanzo tungamira kune urombo kodhi yemhando.

Kugadzirisa dambudziko iri, zvipikirwa zvakawedzerwa kuJavaScript. Vanokutendera kuti utore nzvimbo yakadzika nesting yecallbacks neshoko .then.

Chinhu chakanaka chezvipikirwa ndechekuti ivo vanoita kuti kodhi iverengeke zviri nani, kubva kumusoro kusvika pasi pane kubva kuruboshwe kuenda kurudyi. Zvisinei, zvipikirwa zvinewo matambudziko azvo:

  • Unofanira kuwedzera zvakawanda .ipapo.
  • Panzvimbo yekuedza/kubata, .catch inoshandiswa kubata zvikanganiso zvese.
  • Kushanda nezvivimbiso zvakawanda mukati mechiuno chimwe chete hakusi nyore nguva dzose; mune dzimwe nguva, ivo vanoomesa kodhi.

Heino dambudziko richaratidza zvinoreva pfungwa yekupedzisira.

Ngatitii tine yelop inodhinda nhevedzano yenhamba kubva pa0 kusvika ku10 panguva isina kurongeka (0–n masekonzi). Uchishandisa zvipikirwa, unofanirwa kushandura iyi loop kuitira kuti nhamba dzidhindwe munhevedzano kubva 0 kusvika 10. Saka, kana zvichitora 6 seconds kudhinda zero uye 2 seconds kudhinda imwe, zero inofanira kudhindwa kutanga, uye ipapo. kuverengera kudhinda imwe kuchatanga.

Uye zvechokwadi, hatishandisi Async/Await kana .sort kugadzirisa dambudziko iri. Muenzaniso mhinduro iri kumagumo.

Async mabasa

Kuwedzerwa kweasync mabasa muES2017 (ES8) kwakarerutsa basa rekushanda nezvipikirwa. Ini ndinocherechedza kuti async mabasa anoshanda "pamusoro" yezvipikirwa. Aya mabasa haamiriri pfungwa dzakasiyana. Async mabasa anoitirwa seimwe nzira kune kodhi inoshandisa zvivimbiso.

Async / Wakamirira inoita kuti zvikwanise kuronga basa neasynchronous kodhi mune inopindirana maitiro.

Saka, kuziva zvipikirwa kunoita kuti zvive nyore kunzwisisa misimboti yeAsync/Kumirira.

nemarongerwo

Kazhinji iyo ine maviri akakosha mazwi: async uye kumirira. Izwi rekutanga rinoshandura basa kuita asynchronous. Mabasa akadaro anobvumira kushandiswa kwekumirira. Mune imwewo nyaya, kushandisa basa iri kunoburitsa kukanganisa.

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

Async inoiswa kwekutanga chaiko kwechiziviso chebasa, uye kana iri yebasa remuseve, pakati pe "=" chiratidzo uye maparentheses.

Aya mabasa anogona kuiswa muchinhu semitoo kana kushandiswa muchiziviso chekirasi.

// 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! Zvakakodzera kuyeuka kuti vagadziri vekirasi uye vanotora / seta havagone kuve asynchronous.

Semantics uye mitemo yekuuraya

Async mabasa akafanana neakajairwa JS mabasa, asi pane anosiya.

Saka, async mabasa anogara achidzorera zvivimbiso:

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

Kunyanya, fn inodzosa tambo mhoro. Zvakanaka, sezvo iri iri asynchronous basa, kukosha kwetambo kwakaputirwa muchivimbiso uchishandisa muvaki.

Heino imwe dhizaini isina Async:

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

Muchiitiko ichi, chivimbiso chinodzorerwa "nemaoko". Basa reasynchronous rinogara rakaputirwa muvimbiso itsva.

Kana kukosha kwekudzoka kuri kwechinyakare, iyo async basa inodzosera kukosha nekuiputira muchivimbiso. Kana kukosha kwekudzoka chinhu chechipikirwa, kugadzirisa kwayo kunodzorerwa muvimbiso itsva.

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

Asi chii chinoitika kana paine chikanganiso mukati measynchronous function?

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

Kana ikasagadziriswa, foo() inodzosa vimbiso nekuramba. Pakadai, Promise.ramba ine chikanganiso ichadzoserwa pachinzvimbo chePromise.resolve.

Async mabasa anogara achiburitsa vimbiso, zvisinei kuti chii chinodzoserwa.

Asynchronous function imbomira pane zvese zvakamirira.

Kumirira kunokanganisa matauriro. Saka, kana kutaura kuri vimbiso, iyo async basa inomiswa kusvika vimbiso yazadzikiswa. Kana chirevo chisiri chivimbiso, chinoshandurwa kuita chivimbiso kuburikidza nePromise.resolve uye yopera.

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

Uye heino tsananguro yekuti fn basa rinoshanda sei.

  • Mushure mekuidaidza, mutsara wekutanga unoshandurwa kubva ku const a = kumirira 9; in const a = kumirira Promise.resolve(9);.
  • Mushure mekushandisa Kumirira, basa rekuita rinomiswa kusvika a yawana kukosha kwayo (mumamiriro ezvinhu aripo ikozvino 9).
  • delayAndGetRandom(1000) inombomira kuitwa kwefn basa kusvika yazvipedza (mushure mesekondi imwe). Izvi zvinonyatso misa iyo fn basa kwesekondi imwe.
  • delayAndGetRandom(1000) kuburikidza nekugadzirisa inodzosa kukosha kwakasarudzika, iyo inozopihwa kune musiyano b.
  • Zvakanaka, nyaya ine vhezheni c yakafanana neyekusiyana a. Mushure meizvozvo, zvese zvinomira kwesekondi, asi ikozvino kunonokaAndGetRandom(1000) hapana chinodzosa nekuti hachidiwe.
  • Nekuda kweizvozvo, kukosha kunoverengerwa uchishandisa formula a + b * c. Mhedzisiro yakaputirwa muchivimbiso uchishandisa Promise.resolve uye inodzoserwa nebasa.

Kumbomira uku kungave kuyeuchidza majenareta muES6, asi pane chimwe chinhu pazviri zvikonzero zvako.

Kugadzirisa dambudziko

Zvakanaka, zvino ngatitarisei mhinduro yedambudziko rataurwa pamusoro apa.

Iyo finishMyTask basa rinoshandisa Kumirira kumirira mhedzisiro yekushanda senge queryDatabase, sendEmail, logTaskInFile, nevamwe. Kana ukaenzanisa mhinduro iyi neiyo yakashandiswa zvipikirwa, kufanana kuchava pachena. Nekudaro, iyo Async / Yakamirira vhezheni inorerutsa zvakanyanya kuoma kwese syntactic. Muchiitiko ichi, hapana nhamba huru yecallbacks nemaketani akafanana .then/.catch.

Heino mhinduro ine kubuda kwenhamba, pane zvingasarudzwa zviviri.

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

Uye heino mhinduro uchishandisa async mabasa.

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

Kukanganisa kugadzirisa

Mhosho dzisina kugadziriswa dzinoputirwa nevimbiso yakarambwa. Nekudaro, async mabasa anogona kushandisa edza/kubata kubata zvikanganiso synchronously.

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() ibasa risingawirirani rinobudirira ("nhamba yakakwana") kana kutadza nekukanganisa ("Ndine urombo, nhamba yakakura kwazvo").

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

Sezvo muenzaniso uri pamusoro uchitarisira kuti canRejectOrReturn iite, kutadza kwayo pachayo kunoguma nekuitwa kwechivharo chekubata. Nekuda kweizvozvo, iro basa foo rinopera neisina kutsanangurwa (kana pasina chinodzoserwa muyedzo block) kana paine chikanganiso chakabatwa. Nekuda kweizvozvo, basa iri harikundikane nekuti kuyedza/kubata kuchabata basa foo pacharo.

Heino mumwe muenzaniso:

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

Zvakakodzera kuteerera kune chokwadi chekuti mumuenzaniso, canRejectOrReturn inodzoserwa kubva foo. Foo mune iyi kesi inoguma nenhamba yakakwana kana kudzosa Chikanganiso ("Ndine urombo, nhamba yakakura kwazvo"). Chivharo chekubata hachizombofa chakaitwa.

Dambudziko nderekuti foo anodzosa vimbiso yakapfuura kubva kucanRejectOrReturn. Saka mhinduro ku foo inova mhinduro ku canRejectOrReturn. Muchiitiko ichi, kodhi ichave nemitsara miviri chete:

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

Hezvino izvo zvinoitika kana iwe ukashandisa await uye kudzoka pamwe chete:

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

Mune kodhi iri pamusoro, foo ichabuda zvakabudirira nenhamba yakakwana uye kukanganisa kwakabatwa. Hapazovi nekuramba apa. Asi foo ichadzoka ne canRejectOrReturn, kwete isina kutsanangurwa. Ngative nechokwadi cheizvi nekubvisa mutsara wekudzoka canRejectOrReturn() mutsara:

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

Kukanganisa kwakajairika nemisungo

Mune zvimwe zviitiko, kushandisa Async / Kumirira kunogona kutungamirira kuzvikanganiso.

Kukanganwa kumirira

Izvi zvinoitika kazhinji - izwi rekumirira rinokanganwika pamberi pevimbiso:

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

Sezvauri kuona, hapana kumirira kana kudzoka mukodhi. Naizvozvo foo anogara achibuda asina kutsanangurwa pasina kunonoka 1 sekondi. Asi chipikirwa chacho chichazadzika. Kana ikakanda kukanganisa kana kuramba, ipapo UnhandledPromiseRejectionWarning ichadaidzwa.

Async Mabasa muCallbacks

Async mabasa anowanzo shandiswa mu.map kana .filter semacallbacks. Muenzaniso ndeye fetchPublicReposCount(username) basa, rinodzosa nhamba yeakavhurika repositori paGitHub. Ngatitii kune vashandisi vatatu vane metrics yatinoda. Heino kodhi yebasa iri:

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

Tinoda ArfatSalman, octocat, novig account. Muchiitiko ichi tinoita:

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

Zvakakodzera kuteerera kumirira mu.map callback. Heano maverengero akatevedzana ezvivimbiso, uye .mepu inharembozha isingazivikanwe kumushandisi wega wega.

Kunyanya kuenderana kushandiswa kwekumirira

Ngatitorei iyi kodhi semuenzaniso:

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 nhamba ye repo inoiswa munhamba yekuverenga, ipapo nhamba iyi inowedzerwa kuhuwandu hwekuverenga. Dambudziko nekodhi nderekuti kusvikira data rekutanga remushandisi rasvika kubva kuseva, vese vanotevera vashandisi vachange vari mukumira. Saka, mushandisi mumwe chete anogadziriswa panguva.

Kana, semuenzaniso, zvinotora anenge 300 ms kugadzirisa mushandisi mumwe, saka kune vese vashandisi yatove yechipiri; iyo nguva inoshandiswa mumutsara zvinoenderana nehuwandu hwevashandisi. Asi sezvo kuwana nhamba ye repo hakubvi pane mumwe nemumwe, maitiro anogona kufananidzwa. Izvi zvinoda kushanda ne.map uye Promise.all:

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

Vimbiso.zvose zvinogashira nhevedzano yezvivimbiso sekuisa uye zvinodzosera vimbiso. Iyo yekupedzisira, mushure mekunge zvipikirwa zvese zviri muhurongwa zvapera kana pakurambwa kwekutanga, zvinopedzwa. Zvinogona kuitika kuti vese havatangi panguva imwe chete - kuitira kuti uve nechokwadi chekutanga panguva imwe chete, unogona kushandisa p-mepu.

mhedziso

Async mabasa ari kuwedzera kukosha mukusimudzira. Zvakanaka, kuitira kugadzirisa kushandiswa kweasync mabasa, iwe unofanirwa kushandisa Async Iterators. Mugadziri weJavaScript anofanira kunge akanyatsoziva izvi.

Skillbox inokurudzira:

Source: www.habr.com

Voeg