asynchronní &čekat

Sliby JavaScriptu byly v JavaScriptu zjevením a poskytovaly alternativu k peklu zpětného volání JavaScriptu, ve kterém jsme se rychle ocitli.  Sliby nám také umožnily zavést a lépe zvládat asynchronní úlohy. I když sliby byly zlepšením oproti peklu zpětného volání, stále vyžadují spoustu then s které se mohou stát chaotickými. Opravdu jsem se rozhodl pro ES2017 async a await klíčová slova pro zjednodušení vyřizování slibů. Podívejme se na async a await !

Rychlé základy

  • async je klíčové slovo pro deklaraci funkce
  • await se používá při zpracování příslibu
  • await musí být použito v rámci async i když Chrome nyní podporuje "top level" await
  • async funkce vrátí slib, bez ohledu na to, co je return hodnota je v rámci funkce
  • async /await a sliby jsou pod kapotou v podstatě stejné
  • Nyní je k dispozici ve většině prohlížečů a také v Node.js

Výhody async a await

  • Váš kód je jednodušší a přesnější
  • Ladění je jednodušší díky menšímu počtu zpětných volání
  • Konverze ze slibu then / catch kód je snadný
  • Váš kód může být více "shora dolů", méně vnořený

Základní async a await Ilustrace

Vždy je nejjednodušší se učit z příkladu, takže se podívejme na velmi jednoduchý async / await použití:

// Function declared as async so await can be used
async function fetchContent() {
  // Instead of using fetch().then, use await
  let content = await fetch('/');
  let text = await content.text();
  
  // Inside the async function text is the request body
  console.log(text);

  // Resolve this async function with the text
  return text;
}

// Use the async function
var promise = fetchContent().then(...);

Začněte deklarováním funkce jako async; tato deklarace umožňuje await k použití zevnitř. await klíčové slovo je pak následováno akcí poskytující slib, což je samozřejmě fetch API je. Asynchronní rutina (fetch v tomto případě) běží a provádění dalšího kódu se zastaví (ačkoli neblokuje), dokud neskončí asynchronní akce. Funkce se pak vyřeší pomocí return hodnota a slib se vrátí.

V podstatě můžete udržet svůj kód „inline“ bez nutnosti zpětných volání. Je to asynchronní o něco jednodušší!

Převod Promise Handling na await

Je velká šance, že budete chtít svůj slibový kód aktualizovat, až bude čas. Pojďme si projít příslib aktualizace na await :

// Before: callback city!
fetch('/users.json')
  .then(response => response.json())
  .then(json => {
    console.log(json);
  })
  .catch(e => { console.log('error!'); })

// After: no more callbacks!
async function getJson() {
  try {
    let response = await fetch('/users.json');
    let json = await response.json();
    console.log(json);
  }
  catch(e) {
    console.log('Error!', e);
  }
}

Přepočet ze zatížení then s na await se snadno provádí a váš kód snad vypadá trochu udržitelně!

async / await Vzory

async můžete deklarovat několika způsoby funkce.

Anonymní asynchronní funkce

let main = (async function() {
  let value = await fetch('/');
})();

Deklarace asynchronní funkce

async function main() {
  let value = await fetch('/');
};

Asynchronní přiřazení funkcí

let main = async function() {
  let value = await fetch('/');
};

// Arrow functions too!
let main = async () => {
  let value = await fetch('/');
};

Asynchronní funkce jako argument

document.body.addEventListener('click', async function() {
  let value = await fetch('/');
});

Metody objektů a tříd

// Object property
let obj = {
  async method() {
    let value = await fetch('/');
  }
};

// Class methods
class MyClass {
  async myMethod() {
    let value = await fetch('/');
  }
}

Jak můžete vidět, přidání async je opravdu snadné a pojme všechny pracovní postupy vytváření funkcí!

Zpracování chyb

Tradiční použití slibu vám umožňuje používat catch zpětné volání k vyřešení odmítnutí. Když použijete await , nejlepší je použít try /catch :

try {
  let x = await myAsyncFunction();
}
catch(e) {
 // Error!
}

Staré try /catch není tak okouzlující jako slibovaný catch zpětného volání, ale je stejně efektivní.

Paralelismus

Jake Archibald ze společnosti Google uvádí v dokumentu Async functions skvělé body o tom, že není příliš sekvenční s vaším await s. Cílem je vyhnout se čekání na skládání, pokud je to možné, a místo toho spouštět úlohy okamžitě a používat await po uvedené úlohy jsou spuštěny:

// Will take 1000ms total!
async function series() {
  await wait(500);
  await wait(500);
  return "done!";
}

// Would take only 500ms total!
async function parallel() {
  const wait1 = wait(500);
  const wait2 = wait(500);
  await wait1;
  await wait2;
  return "done!";
}

První blok je špatný, protože druhý wait nastane po prvním wait dokončí. Druhý blok je lepší metoda:spusťte obě wait hovory a pak použijte await; to umožňuje, aby asynchronní funkce probíhaly souběžně!

Promise.all Ekvivalenty

Jedna z mých oblíbených funkcí Promise API je Promise.all , který po dokončení všech načtení spustí zpětné volání. Neexistuje žádný přímý async / await ekvivalent, ale tento příspěvek poskytuje dobrý ekvivalent:

let [foo, bar] = await Promise.all([getFoo(), getBar()]);

Pamatujte si, že async / await jsou v podstatě stejné jako sliby hluboko uvnitř, takže jednoduše čekáme na vyřešení agregovaného slibu!

Nyní můžete použít async a await ve všech hlavních prohlížečích. Tato nová klíčová slova jsou také dostupná v Node.js; starší verze Node.js mohou používat transform-async-to-generator babel plugin pro použití async a await dnes. Sliby jsou stále vynikající, ale díky async je lze lépe udržovat a await !