Andeha hojerentsika ny Async/Await amin'ny JavaScript mampiasa ohatra

Ny mpanoratra ny lahatsoratra dia mandinika ohatra momba ny Async/Await amin'ny JavaScript. Amin'ny ankapobeny, Async/Await dia fomba mety hanoratana kaody asynchronous. Talohan'ny nisehoan'ity endri-javatra ity dia nosoratana tamin'ny fampiasana antso sy fampanantenana ny code toy izany. Ny mpanoratra ny lahatsoratra tany am-boalohany dia manambara ny tombony amin'ny Async/Await amin'ny famakafakana ohatra isan-karazany.

Mampahatsiahy izahay: ho an'ny mpamaky rehetra ny "Habr" - fihenam-bidy 10 roubles rehefa misoratra anarana amin'ny taranja Skillbox rehetra mampiasa ny code promotional "Habr".

Skillbox dia manoro hevitra: Fampianarana an-tserasera "Java developer".

callback

Callback dia fiasa izay mihemotra amin'ny fotoana tsy voafetra ny antso. Teo aloha, ny antso miverina dia nampiasaina tamin'ireo faritra misy kaody izay tsy azo avy hatrany ny valiny.

Ity misy ohatra iray amin'ny famakiana rakitra iray ao amin'ny Node.js asynchronously:

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

Mipoitra ny olana rehefa mila manao hetsika asynchronous maromaro indray mandeha ianao. Alao sary an-tsaina ity toe-javatra ity: misy fangatahana atao amin'ny angon-drakitra mpampiasa Arfat, mila mamaky ny saha profile_img_url ianao ary misintona sary avy amin'ny server someserver.com.
Aorian'ny fampidinana dia avadika ho endrika hafa ny sary, ohatra avy amin'ny PNG mankany JPEG. Raha nahomby ny fiovam-po dia misy taratasy alefa any amin'ny mailaka an'ny mpampiasa. Avy eo, ampidirina ao amin'ny rakitra transformations.log ny fampahalalana momba ny hetsika, manondro ny daty.

Tena ilaina ny mandinika ny fifandimbiasan'ny antso miverina sy ny isan'ny }) amin'ny ampahany farany amin'ny kaody. Antsoina hoe Callback Hell na Pyramid of Doom izany.

Ny tsy fahampian'ity fomba ity dia miharihary:

  • Sarotra vakina ity kaody ity.
  • Sarotra ihany koa ny mikarakara lesoka, izay matetika mitarika ho amin'ny kalitaon'ny kaody ratsy.

Mba hamahana ity olana ity dia nampiana fampanantenana ny JavaScript. Izy ireo dia mamela anao hanoloana fanaingoana lalina ny antso miverina amin'ny teny .avy eo.

Ny lafiny tsara amin'ny fampanantenana dia ny mahatonga ny kaody ho mora vakiana kokoa, hatrany ambony ka hatrany ambany fa tsy miankavia miankavanana. Na izany aza, manana ny olan'izy ireo koa ny fampanantenana:

  • Mila manampy be dia be ny .avy eo.
  • Ho solon'ny try/catch, .catch no ampiasaina hamahana ny lesoka rehetra.
  • Tsy mora foana ny miasa miaraka amin'ny fampanantenana maromaro ao anatin'ny loop iray;

Ity misy olana izay hampiseho ny dikan'ny teboka farany.

Eritrereto hoe manana loop for izay manonta filaharan'ny isa 0 ka hatramin'ny 10 amin'ny elanelana kisendrasendra (0–n segondra). Amin'ny fampiasana fampanantenana, mila manova an'io tadivavarana io ianao mba hanontany ny isa amin'ny filaharana manomboka amin'ny 0 ka hatramin'ny 10. Noho izany, raha 6 segondra ny fanontana aotra ary 2 segondra ny fanontana iray, ny aotra dia tokony atao pirinty aloha, ary avy eo manomboka ny fanisana ny fanontana ny iray.

Ary mazava ho azy, tsy mampiasa Async/Await na .sort izahay hamahana ity olana ity. Vahaolana ohatra dia any amin'ny farany.

Async functions

Ny fanampin'ny asa async ao amin'ny ES2017 (ES8) dia nanatsotra ny asa amin'ny fampanantenana. Marihiko fa miasa "eo ambonin'ny" fampanantenana ny asa async. Ireo asa ireo dia tsy maneho hevitra samy hafa qualitative. Ny fiasa Async dia natao ho solon'ny kaody mampiasa fampanantenana.

Async/Await dia ahafahana mandamina ny asa miaraka amin'ny kaody asynchronous amin'ny fomba synchronous.

Noho izany, ny fahafantarana fampanantenana dia manamora ny fahazoana ny fitsipiky ny Async/Await.

Syntaxe

Amin'ny ankapobeny dia misy teny fototra roa: async sy miandry. Ny teny voalohany dia mamadika ny asa ho asynchronous. Ny fiasa toy izany dia mamela ny fampiasana ny miandry. Amin'ny tranga hafa rehetra, ny fampiasana an'io fiasa io dia hiteraka hadisoana.

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

Async dia ampidirina eo am-piandohan'ny fanambarana asa, ary amin'ny trangan'ny zana-tsipìka, eo anelanelan'ny famantarana "=" sy ny fononteny.

Ireo fiasa ireo dia azo apetraka amin'ny zavatra iray ho fomba na ampiasaina amin'ny fanambarana kilasy.

// 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! Tsara hotadidina fa tsy azo asynchronous ny mpanamboatra kilasy sy getter/setter.

Semantika sy fitsipika famonoana

Ny fiasa Async dia mitovy amin'ny fiasa JS mahazatra, saingy misy ny maningana.

Noho izany, ny asa async dia mamerina fampanantenana foana:

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

Amin'ny ankapobeny, ny fn dia mamerina ny tady hello. Eny, satria asa asynchronous ity, ny sandan'ny string dia fonosina amin'ny fampanantenana mampiasa mpanamboatra.

Ity misy endrika hafa tsy misy Async:

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

Amin'ity tranga ity, ny fampanantenana dia averina "manana". Ny fiasa asynchronous dia voafono amina fampanantenana vaovao foana.

Raha primitive ny sanda miverina, ny asa async dia mamerina ny sanda amin'ny famenoana azy amin'ny fampanantenana. Raha zavatra fampanantenana ny sanda miverina dia averina amin'ny fampanantenana vaovao ny famahana azy.

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

Inona anefa no mitranga raha misy hadisoana ao anatin'ny fiasa asynchronous?

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

Raha tsy voakarakara, foo() dia hamerina fampanantenana miaraka amin'ny fandavana. Amin'ity toe-javatra ity, Promise.reject misy hadisoana no haverina fa tsy Promise.resolve.

Ny asa Async dia mamoaka fampanantenana foana, na inona na inona averina.

Miato ny fiasa asynchronous isaky ny miandry.

Misy fiantraikany amin'ny fanehoan-kevitra ny miandry. Noho izany, raha fampanantenana ilay fitenenana, dia miato ny asa async mandra-pahatanterahan'ilay fampanantenana. Raha tsy fampanantenana ilay teny dia avadika ho fampanantenana amin'ny alalan'ny Promise.resolve ary vita avy eo.

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

Ary ity misy famaritana ny fomba fiasan'ny fn.

  • Rehefa avy niantso azy, ny andalana voalohany dia niova fo avy amin'ny const a = miandry 9; in const a = miandry Promise.resolve(9);.
  • Aorian'ny fampiasana Await dia miato ny fampandehanana asa mandra-pahazoan'ny a (amin'ny toe-javatra ankehitriny dia 9).
  • delayAndGetRandom(1000) dia mampiato ny fanatanterahana ny asa fn mandra-pahavitan'ny tenany (aorian'ny 1 segondra). Izany dia mampiato ny fiasan'ny fn mandritra ny 1 segondra.
  • delayAndGetRandom(1000) amin'ny alΓ lan'ny vahaolana dia mamerina sanda kisendrasendra, izay apetraka amin'ny variable b.
  • Eny, ny tranga misy variable c dia mitovy amin'ny tranga misy variable a. Aorian'izay dia mijanona mandritra ny segondra iray ny zava-drehetra, fa ankehitriny ny delayAndGetRandom(1000) dia tsy mamerina na inona na inona satria tsy ilaina izany.
  • Vokatr'izany, ny soatoavina dia kajy amin'ny fampiasana ny formula a + b * c. Ny vokatra dia nofonosina fampanantenana mampiasa Promise.resolve ary averina amin'ny asa.

Ireo fiatoana ireo dia mety mampahatsiahy ireo mpamokatra ao amin'ny ES6, saingy misy zavatra azo atao ny antony.

Famahana ny olana

Eny ary, andeha hojerentsika ny vahaolana amin'ny olana voalaza etsy ambony.

Ny asa finishMyTask dia mampiasa Await hiandry ny valin'ny asa toy ny queryDatabase, sendEmail, logTaskInFile, sy ny hafa. Raha ampitahainao amin'ilay nampiasana fampanantenana io vahaolana io, dia hiharihary ny fitoviana. Na izany aza, ny dikan-teny Async/Await dia manamora ny fahasarotana syntactic rehetra. Amin'ity tranga ity dia tsy misy antso an-tariby sy rojo maro toy ny .then/.catch.

Ity misy vahaolana amin'ny famoahana isa, misy safidy roa.

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

Ary ity misy vahaolana amin'ny fampiasana async functions.

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

Error fanodinana

Ny hadisoana tsy voafehy dia nofonosina fampanantenana nolavina. Na izany aza, ny asa async dia afaka mampiasa try/catch mba hamahana ny lesoka miaraka.

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() dia fiasa asynchronous izay mahomby ("isa tonga lafatra") na tsy mahomby amin'ny fahadisoana ("Miala tsiny fa lehibe loatra ny isa").

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

Satria ny ohatra etsy ambony dia manantena ny canRejectOrReturn hotanterahina, ny tsy fahombiazany dia hiteraka famonoana ny sakana fisamborana. Vokatr'izany, ny asa foo dia hifarana amin'ny tsy voafaritra (rehefa tsy misy naverina ao amin'ny sakana andrana) na misy hadisoana tratra. Vokatr'izany dia tsy hahomby io fiasa io satria ny try/catch no handamina ny asa foo.

Ity misy ohatra iray hafa:

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

Ilaina ny mandinika ny zava-misy fa amin'ny ohatra, ny canRejectOrReturn dia averina avy amin'ny foo. Foo amin'ity tranga ity dia mifarana amin'ny isa tonga lafatra na mamerina Error (β€œMiala tsiny fa lehibe loatra ny isa”). Tsy ho tanteraka mihitsy ny sakana fisamborana.

Ny olana dia ny foo mamerina ny fampanantenana azo avy amin'ny canRejectOrReturn. Ka ny vahaolana amin'ny foo dia lasa vahaolana amin'ny canRejectOrReturn. Amin'ity tranga ity, ny kaody dia tsy ahitana afa-tsy andalana roa:

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

Izao no mitranga raha miara-miandrasana sy miverina ianao:

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

Ao amin'ny kaody etsy ambony, foo dia hivoaka soa aman-tsara miaraka amin'ny isa tonga lafatra sy ny fahadisoana tratra. Tsy hisy fandavana eto. Saingy hiverina amin'ny canRejectOrReturn ny foo, fa tsy amin'ny tsy voafaritra. Andao ho azo antoka izany amin'ny alΓ lan'ny fanesorana ny fiverenana miandry canRejectOrReturn() andalana:

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

Fahadisoana sy fandrika mahazatra

Amin'ny tranga sasany, ny fampiasana Async/Await dia mety hitarika amin'ny fahadisoana.

Adino miandry

Mitranga matetika izany - hadino alohan'ny fampanantenana ny teny fanalahidy miandry:

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

Araka ny hitanao dia tsy misy fiandrasana na fiverenana ao amin'ny code. Noho izany ny foo dia mivoaka miaraka amin'ny tsy voafaritra tsy misy hatak'andro 1 segondra. Fa ho tanteraka ny fampanantenana. Raha misy hadisoana na fandavana, dia antsoina ny UnhandledPromiseRejectionWarning.

Async Functions amin'ny Callbacks

Ny asa Async dia matetika ampiasaina amin'ny .map na .sivana ho antso miverina. Ohatra iray ny fetchPublicReposCount(anaran'ny mpampiasa), izay mamerina ny isan'ny tahiry misokatra ao amin'ny GitHub. Andeha hatao hoe misy mpampiasa telo manana ny metrika ilaintsika. Ity ny code ho an'ity asa ity:

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

Mila kaonty ArfatSalman, octocat, norvig izahay. Amin'ity tranga ity dia manao:

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

Tena ilaina ny mandinika ny Await ao amin'ny .map callback. Ireto misy fampanantenana maromaro, ary ny .map dia antso tsy fantatra anarana ho an'ny mpampiasa tsirairay.

Fampiasana tsy miovaova be loatra ny miandry

Andeha horaisintsika ho ohatra ity code ity:

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

Eto ny laharan'ny repo dia apetraka ao amin'ny fari-pahaizan'ny isa, avy eo ampidirina amin'ny laharan'ny isa io isa io. Ny olana amin'ny kaody dia ny hoe mandra-pahatongan'ny angon'ny mpampiasa voalohany avy amin'ny mpizara, ny mpampiasa rehetra manaraka dia ho eo amin'ny mode standby. Noho izany, mpampiasa iray ihany no karakaraina amin'ny fotoana iray.

Raha, ohatra, dia mila 300 ms eo ho eo ny fanodinana mpampiasa iray, dia ho an'ny mpampiasa rehetra dia efa iray segondra ny fotoana lany amin'ny linear ny isan'ny mpampiasa. Saingy satria ny fahazoana ny isan'ny repo dia tsy miankina amin'ny tsirairay, ny dingana dia azo ampitahaina. Mitaky fiaraha-miasa amin'ny .map sy Promise.all izany:

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

Ny Promise.all dia mahazo fampanantenana maromaro ho fampidirana ary mamerina fampanantenana. Ity farany, rehefa vita ny fampanantenana rehetra ao amin'ny array na amin'ny fandavana voalohany, dia vita. Mety hitranga fa tsy manomboka amin'ny fotoana iray izy rehetra - mba hahazoana antoka ny fanombohana miaraka, azonao atao ny mampiasa p-map.

famaranana

Lasa manan-danja hatrany amin'ny fampandrosoana ny fiasa Async. Eny, ho an'ny fampiasana adaptive ny asa async dia tokony hampiasainao ianao Async Iterators. Ny mpamorona JavaScript dia tokony hahay tsara amin'izany.

Skillbox dia manoro hevitra:

Source: www.habr.com

Add a comment