Se'i o tatou va'ai i le Async/Await i le JavaScript e fa'aaoga ai fa'ata'ita'iga

O le tusitala o le tusiga o loʻo suʻesuʻeina faʻataʻitaʻiga o Async/Await in JavaScript. Aotelega, Async/Await o se auala faigofie e tusi ai le code asynchronous. Aʻo leʻi faʻaalia lenei faʻaaliga, na tusia sea code e faʻaaoga ai callbacks ma folafolaga. O le tusitala o le uluai tusiga o loʻo faʻaalia ai le lelei o Async / Await e ala i le suʻeina o faʻataʻitaʻiga eseese.

Matou te faʻamanatu atu ia te oe: mo tagata faitau uma o le "Habr" - o se faʻaitiitiga o 10 rubles pe a lesitala i soʻo se vasega Skillbox e faʻaaoga ai le code promotional "Habr".

Ua fautuaina e Skillbox: A'oa'oga i luga ole laiga "Fa'atupu Java".

callback

O le toe fo'i i tua ose galuega e tuai ona vala'au e fa'avavau. I le taimi muamua, sa fa'aoga toe fo'i i vaega o fa'ailoga e le'i mafai ona maua vave le fa'ai'uga.

O se faʻataʻitaʻiga lea o le faitau faʻatasi o se faila i Node.js:

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

O faʻafitauli e tulaʻi mai pe a manaʻomia le faʻatinoina o le tele o gaioiga asynchronous i le taimi e tasi. Sei o tatou mafaufau i lenei faʻataʻitaʻiga: o se talosaga e faia i le Arfat user database, e tatau ona e faitau i lona profile_img_url field ma sii mai se ata mai le server someserver.com.
A uma ona sii mai, matou te faaliliuina le ata i se isi faatulagaga, mo se faʻataʻitaʻiga mai le PNG i le JPEG. Afai na manuia le liua, e lafo atu se tusi i le imeli a le tagata fa'aoga. O le isi, o faʻamatalaga e uiga i le mea na tupu o loʻo tuʻuina atu i le transformations.log file, faʻaalia le aso.

E taua le gauai atu i le faʻapipiʻiina o toe foʻi ma le numera tele o }) i le vaega mulimuli o le code. Ua ta'ua o le Callback Hell po o le Pyramid of Doom.

O le le lelei o lenei metotia e iloagofie:

  • O lenei code e faigata ona faitau.
  • E faigata foi ona taulimaina mea sese, lea e masani ona taʻitaʻia ai le lelei o le code code.

Ina ia foia lenei faafitauli, sa faaopoopo atu folafolaga i le JavaScript. Latou te fa'atagaina oe e sui le fa'aputuga loloto o valaau i tua i le upu .ona.

O le itu lelei o folafolaga o le latou faia lea o le code e sili atu ona faigofie ona faitau, mai luga i lalo nai lo le agavale i le taumatau. Ae ui i lea, o folafolaga e iai foi o latou faafitauli:

  • E tatau ona e faʻaopoopoina le tele o .ona.
  • Nai lo le taumafai/pu'e, .catch e fa'aoga e fa'atautaia uma mea sese.
  • O le galue ma le tele o folafolaga i totonu o le tasi matasele e le faigofie i taimi uma, i nisi tulaga, latou te faʻalavelaveina le code.

O se fa'afitauli lea o le a fa'aalia ai le uiga o le manatu mulimuli.

Fa'apea e iai la tatou matasele mo e lolomi ai se faasologa o fuainumera mai le 0 i le 10 i taimi fa'afuase'i (0–n sekone). I le faʻaaogaina o folafolaga, e tatau ona e suia lenei matasele ina ia lolomi numera i le faasologa mai le 0 i le 10. O lea, afai e manaʻomia le 6 sekone e lolomi ai se zero ma 2 sekone e lolomi ai se tasi, e tatau ona lolomi muamua le zero, ona o le a amata le countdown mo le lolomiina o le tasi.

Ma o le mea moni, matou te le faʻaogaina Async / Await poʻo .sort e foia ai lenei faʻafitauli. O se faʻataʻitaʻiga fofo o loʻo i le pito.

Async galuega

O le faʻaopoopoga o galuega async i le ES2017 (ES8) faʻafaigofie le galuega o le galue ma folafolaga. Ou te maitauina o galuega async e galue "i luga" o folafolaga. O nei galuega tauave e le o fa'atusalia ai ni manatu uiga ese. O galuega a Async o loʻo faʻamoemoeina e fai ma sui i code e faʻaogaina ai folafolaga.

O le Async/Await e mafai ai ona fa'atulaga galuega fa'atasi ma fa'ailoga asynchronous i se sitaili fa'atasi.

O le mea lea, o le iloaina o folafolaga e faigofie ai ona malamalama i mataupu faavae o Async/Await.

Faʻailoga

E masani lava e lua upu autu: async ma faatalitali. O le upu muamua e liliu le galuega i le asynchronous. O ia galuega e mafai ai ona faʻaogaina le faʻatali. I soʻo se isi tulaga, o le faʻaaogaina o lenei galuega o le a faʻaalia ai se mea sese.

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

Async o loʻo faʻaofiina i le amataga o le faʻaaliga o galuega, ma i le tulaga o se galuega arrow, i le va o le "="" faʻailoga ma puipui.

O nei galuega e mafai ona tuʻuina i totonu o se mea e fai ma metotia pe faʻaaogaina i se taʻutinoga a le vasega.

// 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! E taua le manatua e le mafai e tagata fau vasega ma getters/setters ona asynchronous.

Semantics ma tulafono fa'atino

O galuega a Async e tutusa lelei ma galuega masani a le JS, ae o loʻo i ai tuusaunoaga.

O le mea lea, o galuega async e toe faʻafoʻi mai folafolaga:

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

Aemaise lava, fn toe faafoi le manoa talofa. Ia, talu ai o se galuega asynchronous lea, o le manoa taua o loʻo afifi i se folafolaga e faʻaaoga ai se faufale.

O se isi mamanu e aunoa ma Async:

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

I lenei tulaga, o le folafolaga e toe faafoi "lima". O se galuega asynchronous e masani ona afifi i se folafolaga fou.

Afai o le tau toe faafoi o se mea muamua, o le galuega async e toe faafoi le tau e ala i le afifiina i se folafolaga. Afai o le tau toe faafoi o se mea folafola, o lona iuga e toe faafoi i se folafolaga fou.

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

Ae o le a le mea e tupu pe a iai se mea sese i totonu o se galuega asynchronous?

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

Afai e le fa'agaioiina, foo() o le a toe fa'afo'i se folafolaga ma le teena. I le tulaga lea, o le a toe faafoi mai le Promise.reject o iai se mea sese nai lo le Promise.resolve.

O galuega a Async i taimi uma e maua ai se folafolaga, e tusa lava po o le a le mea e toe faafoi mai.

O galuega fa'aasynchronous e malolo i so'o se fa'atali.

Faatalitali e aafia ai faaupuga. O lea la, afai o le faʻamatalaga o se folafolaga, o le async galuega e taofia le tumau seia oʻo ina faataunuuina le folafolaga. Afai o le faaupuga e le o se folafolaga, e liua i se folafolaga e ala i le Promise.resolve ona maeʻa lea.

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

Ma o se faʻamatalaga lenei o le auala e galue ai le fn.

  • A maeʻa ona valaʻau, o le laina muamua e liua mai le const a = faʻatali 9; in const a = faatali Folafolaga.resolve(9);.
  • A maeʻa le faʻaaogaina o le Await, e faʻagata le faʻatinoina o galuega seʻia oʻo ina maua lona tau (i le tulaga o loʻo i ai nei o le 9).
  • delayAndGetRandom(1000) taofi le faʻatinoina o le galuega fn seia maeʻa (pe a uma le 1 sekone). Ole mea lea e taofi lelei ai le galuega fn mo le 1 sekone.
  • delayAndGetRandom(1000) e ala i le fofo e toe faafoi mai ai se tau fa'afuase'i, ona tu'u atu lea i le fesuiaiga b.
  • Ia, o le mataupu i le fesuiaiga c e tutusa ma le mataupu i le fesuiaiga a. A maeʻa lena, e taofi mea uma mo se sekone, ae o le taimi nei o le delayAndGetRandom(1000) e le toe faʻafoʻi se mea ona e le manaʻomia.
  • O se taunuuga, o tau e faʻatatau i le faʻaogaina o le fua a + b * c. O le taunuuga o loʻo afifi i se folafolaga e faʻaaoga ai le Promise.resolve ma toe faʻafoʻi mai e le galuega.

O nei taofi atonu e faamanatu ai afi afi i le ES6, ae o loʻo i ai se mea au mafuaaga.

Foia le faafitauli

Ia, se'i o tatou tilotilo la i le fofo o le faafitauli ua ta'ua i luga.

O le galuega finishMyTask e fa'aaoga ai le Await e fa'atali mo fa'ai'uga o galuega e pei ole queryDatabase, sendImeli, logTaskInFile, ma isi. Afai e te faʻatusatusaina lenei fofo ma le mea na faʻaaogaina ai folafolaga, o le a iloagofie mea tutusa. Ae ui i lea, o le Async/Await version e matua faafaigofieina uma faʻalavelave faʻalavelave. I lenei tulaga, e leai se numera tele o telefoni ma filifili e pei o .then/.catch.

O se fofo lea ma le gaosiga o numera, e lua filifiliga.

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

Ma o se fofo lea e faʻaaoga ai galuega async.

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

Sese faiga

O mea sese e lei taulimaina ua afifiina i se folafolaga ua teena. Ae ui i lea, o galuega async e mafai ona faʻaogaina le taumafai / puʻe e taulimaina faʻaletonu faʻatasi.

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() ose galuega asynchronous e manuia (“numera atoatoa”) pe toilalo i se mea sese (“Malie, numera tele tele”).

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

Talu ai ona o le faʻataʻitaʻiga o loʻo i luga o loʻo faʻamoemoe e mafai ona faʻaalia le mafaiRejectOrReturn, o lona lava toilalo o le a mafua ai le faʻatinoina o le poloka puʻe. O le i'uga, o le galuega foo o le a fa'ai'u i le le fa'amalamalamaina (pe a leai se mea e toe fa'afo'i i le poloka fa'ata'ita'i) po'o se mea sese na maua. O se taunuuga, o le a le toilalo lenei galuega ona o le taumafai / puʻe o le a taulimaina le galuega foo lava ia.

O se isi fa'ata'ita'iga:

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

E taua le gauai atu i le mea moni e faapea i le faʻataʻitaʻiga, canRejectOrReturn ua toe foʻi mai foo. Foo i lenei tulaga a le fa'amuta i se numera atoatoa pe toe fa'afo'i mai se Sese ("Fa'amolemole, numera tele"). Ole poloka pu'e e le mafai lava ona fa'atinoina.

O le faʻafitauli o le foo e toe faʻafoʻi le folafolaga na pasia mai canRejectOrReturn. O lea la o le fofo i le foo ua avea ma fofo i canRejectOrReturn. I lenei tulaga, o le code o le a aofia ai na o laina e lua:

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

O le mea lenei e tupu pe afai e te faʻaoga faʻatali ma toe foʻi faʻatasi:

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

I le code o loʻo i luga, foo o le a alu ese ma le manuia ma se numera atoatoa ma se mea sese na maua. O le a leai se teenaina iinei. Ae o le a toe foʻi foo ma canRejectOrReturn, ae le o le le faʻamalamalamaina. Sei o tatou mautinoa o lenei mea e ala i le aveesea o le toe foʻi faʻatali canRejectOrReturn() laina:

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

Mea sese masani ma mailei

I nisi tulaga, o le faʻaaogaina o Async/Await e mafai ona oʻo atu ai i mea sese.

Ua galo ona faatalitali

E masani ona tupu lenei mea - ua galo le upu fa'atali a'o le'i faia le folafolaga:

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

E pei ona e vaʻai, e leai se faʻatali pe toe foʻi mai i le code. O le mea lea e alu ese ai foo i taimi uma ma le le fa'amalamalamaina e aunoa ma se fa'atuai 1 sekone. Ae o le a faataunuuina le folafolaga. Afai e lafoina se mea sese poʻo le teena, ona valaau lea o UnhandledPromiseRejectionWarning.

Async Galuega i Callbacks

O galuega a Async e masani ona fa'aoga i le .map po'o le .filter e fai ma toe fo'i. O se faʻataʻitaʻiga o le fetchPublicReposCount(username) galuega, lea e toe faʻafoʻi mai ai le numera o faleoloa tatala ile GitHub. Fa'apea e tolu tagata fa'aoga latou metric tatou te mana'omia. O le code lea mo lenei galuega:

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

Matou te manaʻomia ArfatSalman, octocat, norvig tala. I lenei tulaga tatou te faia:

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

E aoga le fa'alogo ile Await ile .map callback. O lo'o fa'atauaina se fa'asologa o folafolaga, ma o le .map ose toe fo'i fa'alilolilo mo tagata fa'aoga ta'itasi.

Fa'aoga faifai pea ole fa'atali

Sei o tatou faia lenei code e fai ma faʻataʻitaʻiga:

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

O iinei o le numera o le repo o loʻo tuʻuina i le numera numera, ona faʻaopoopoina lea o lenei numera i le numera o numera. O le fa'afitauli i le fa'ailoga e fa'apea, se'ia o'o mai fa'amaumauga a le tagata muamua mai le 'au'aunaga, o le a tu'u uma tagata fa'aoga mulimuli ane i le tulaga fa'atali. O lea la, e na'o le tasi le tagata e fa'aogaina i le taimi.

Afai, mo se faʻataʻitaʻiga, e manaʻomia le 300 ms e faʻaogaina ai le tasi tagata faʻaoga, o lona uiga mo tagata faʻaoga uma ua avea ma lona lua le taimi faʻaalu laina faʻalagolago i le numera o tagata faʻaoga. Ae talu ai ona o le mauaina o le numera o le repo e le faʻalagolago le tasi i le isi, o faiga e mafai ona tutusa. Ole mea lea e mana'omia ai le galue i le .map ma le Promise.all:

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

E maua e Promise.all le tele o folafolaga e fai ma sao ma toe faafoi mai se folafolaga. O le mea mulimuli e maeʻa pe a maeʻa folafolaga uma i le array poʻo le teena muamua. Atonu e tupu latou te le amataina uma i le taimi e tasi - ina ia mautinoa le amataga tutusa, e mafai ona e faʻaogaina le p-map.

iʻuga

O galuega a Async ua faʻateleina le taua mo le atinaʻe. Ia, mo le faʻaogaina o galuega async, e tatau ona e faʻaogaina Async Iterators. E tatau ona malamalama lelei se tagata e faia le JavaScript i lenei mea.

Ua fautuaina e Skillbox:

puna: www.habr.com

Faaopoopo i ai se faamatalaga