Dieser Artikel bietet Ihnen eine detaillierte Einführung in die Async-Funktion in ES6 (mit Beispielen). Ich hoffe, dass er für Freunde hilfreich ist.
Der ES2017-Standard führt die Async-Funktion ein, wodurch asynchrone Vorgänge komfortabler werden.
Im Hinblick auf die asynchrone Verarbeitung ist die Async-Funktion der syntaktische Zucker der Generator-Funktion.
Zum Beispiel:
// 使用 generator var fetch = require('node-fetch'); var co = require('co'); function* gen() { var r1 = yield fetch('https://api.github.com/users/github'); var json1 = yield r1.json(); console.log(json1.bio); } co(gen);
Wenn Sie asynchron verwenden:
// 使用 async var fetch = require('node-fetch'); var fetchData = async function () { var r1 = await fetch('https://api.github.com/users/github'); var json1 = await r1.json(); console.log(json1.bio); }; fetchData();
Tatsächlich besteht das Implementierungsprinzip der asynchronen Funktion darin, die Generatorfunktion und den automatischen Executor in eine Funktion darin einzuschließen .
async function fn(args) { // ... } // 等同于 function fn(args) { return spawn(function* () { // ... }); }
Die Spawn-Funktion bezieht sich auf den automatischen Executor, wie zum Beispiel Co.
Darüber hinaus gibt die asynchrone Funktion ein Promise-Objekt zurück. Sie können auch verstehen, dass die asynchrone Funktion eine Kapselungsschicht ist, die auf Promise und Generator basiert.
Genau genommen ist Async eine Syntax und Promise ein integriertes Objekt. Die beiden sind nicht vergleichbar, ganz zu schweigen davon, dass die Async-Funktion auch ein Promise-Objekt zurückgibt. ..
Hier zeigen wir hauptsächlich einige Szenarien, mit denen asynchrone Prozesse eleganter gehandhabt werden als mit Promise.
/** * 示例一 */ function fetch() { return ( fetchData() .then(() => { return "done" }); ) } async function fetch() { await fetchData() return "done" };
/** * 示例二 */ function fetch() { return fetchData() .then(data => { if (data.moreData) { return fetchAnotherData(data) .then(moreData => { return moreData }) } else { return data } }); } async function fetch() { const data = await fetchData() if (data.moreData) { const moreData = await fetchAnotherData(data); return moreData } else { return data } };
/** * 示例三 */ function fetch() { return ( fetchData() .then(value1 => { return fetchMoreData(value1) }) .then(value2 => { return fetchMoreData2(value2) }) ) } async function fetch() { const value1 = await fetchData() const value2 = await fetchMoreData(value1) return fetchMoreData2(value2) };
In diesem Code kann try/catch einige Promise-Konstruktionsfehler in fetchData() erfassen , von JSON.parse ausgelöste Ausnahmen können nicht abgefangen werden. Wenn Sie von JSON.parse ausgelöste Ausnahmen behandeln möchten, müssen Sie eine Catch-Funktion hinzufügen, um die Ausnahmebehandlungslogik zu wiederholen.
In tatsächlichen Projekten kann die Fehlerbehandlungslogik komplex sein, was zu redundantem Code führen kann.
function fetch() { try { fetchData() .then(result => { const data = JSON.parse(result) }) .catch((err) => { console.log(err) }) } catch (err) { console.log(err) } }
Das Aufkommen von async/await ermöglicht es Try/Catch, synchrone und asynchrone Fehler zu erfassen.
async function fetch() { try { const data = JSON.parse(await fetchData()) } catch (err) { console.log(err) } };
Da der Code darin asynchron ausgeführt wird, wird der Code ausgeführt, wenn Sie den Punkt unterbrechen nicht sequentiell ausgeführt werden, insbesondere wenn Sie Step Over verwenden, ruft die Then-Funktion direkt die nächste Then-Funktion auf.
const fetchData = () => new Promise((resolve) => setTimeout(resolve, 1000, 1)) const fetchMoreData = (value) => new Promise((resolve) => setTimeout(resolve, 1000, value + 1)) const fetchMoreData2 = (value) => new Promise((resolve) => setTimeout(resolve, 1000, value + 2)) function fetch() { return ( fetchData() .then((value1) => { console.log(value1) return fetchMoreData(value1) }) .then(value2 => { return fetchMoreData2(value2) }) ) } const res = fetch(); console.log(res);
Wenn Sie Async verwenden, können Sie es genauso debuggen wie synchronen Code debuggen.
asynchrone Hölle bedeutet hauptsächlich, dass Entwickler nach grammatikalischer Einfachheit gierig sind und Inhalte, die parallel ausgeführt werden können, in sequentielle Ausführung umwandeln, was sich auf die Leistung auswirkt, aber die Verwendung der Hölle zur Beschreibung ist eine Etwas übertrieben...
Zum Beispiel:
const fetchData = () => new Promise((resolve) => setTimeout(resolve, 1000, 1)) const fetchMoreData = () => new Promise((resolve) => setTimeout(resolve, 1000, 2)) const fetchMoreData2 = () => new Promise((resolve) => setTimeout(resolve, 1000, 3)) async function fetch() { const value1 = await fetchData() const value2 = await fetchMoreData(value1) return fetchMoreData2(value2) }; const res = fetch(); console.log(res);
getList() und getAnotherList() haben eigentlich keine Abhängigkeit, aber die aktuelle Schreibweise, Obwohl es einfach ist, führt es dazu, dass getAnotherList() erst nach der Rückkehr von getList() ausgeführt wird, wodurch sich die Anforderungszeit verdoppelt.
Um dieses Problem zu lösen, können wir es wie folgt ändern:
(async () => { const getList = await getList(); const getAnotherList = await getAnotherList(); })();
Sie können auch Promise.all() verwenden:
(async () => { const listPromise = getList(); const anotherListPromise = getAnotherList(); await listPromise; await anotherListPromise; })();
Natürlich ist das obige Beispiel relativ einfach, erweitern wir es:
(async () => { Promise.all([getList(), getAnotherList()]).then(...); })();
Aufgrund der Eigenschaften vonwait hat das gesamte Beispiel eine offensichtliche Reihenfolge. GetList() und getAnotherList() haben jedoch tatsächlich keine Die Abhängigkeiten „submit(listData)“ und „submit( anotherListData)“ haben keine Abhängigkeiten. Wie sollten wir dieses Beispiel also umschreiben?
Grundsätzlich in drei Schritte unterteilt:
1. Finden Sie die Abhängigkeiten heraus
Hier muss „submit(listData)“ nach getList() stehen. Submit(anotherListData) muss nach anotherListPromise() stehen.
2. Interdependente Anweisungen in asynchrone Funktionen einschließen
(async () => { const listPromise = await getList(); const anotherListPromise = await getAnotherList(); // do something await submit(listData); await submit(anotherListData); })();
3. Asynchrone Funktionen gleichzeitig ausführen
async function handleList() { const listPromise = await getList(); // ... await submit(listData); } async function handleAnotherList() { const anotherListPromise = await getAnotherList() // ... await submit(anotherListData) }
Frage: Wie implementiert man bei einer Reihe von URLs die Abfolge und Parallelität der Schnittstelle?
asynchrone sekundäre Implementierung:
async function handleList() { const listPromise = await getList(); // ... await submit(listData); } async function handleAnotherList() { const anotherListPromise = await getAnotherList() // ... await submit(anotherListData) } // 方法一 (async () => { const handleListPromise = handleList() const handleAnotherListPromise = handleAnotherList() await handleListPromise await handleAnotherListPromise })() // 方法二 (async () => { Promise.all([handleList(), handleAnotherList()]).then() })()
// 继发一 async function loadData() { var res1 = await fetch(url1); var res2 = await fetch(url2); var res3 = await fetch(url3); return "whew all done"; }
asynchrone gleichzeitige Implementierung:
// 继发二 async function loadData(urls) { for (const url of urls) { const response = await fetch(url); console.log(await response.text()); } }
// 并发一 async function loadData() { var res = await Promise.all([fetch(url1), fetch(url2), fetch(url3)]); return "whew all done"; }
Obwohl wir Try Catch verwenden können, um Fehler zu erfassen, Wenn wir jedoch mehrere Fehler abfangen und unterschiedliche Verarbeitungen durchführen müssen, führt das Ausprobieren von Abfangen schnell zu überladenem Code, z. B.:
// 并发二 async function loadData(urls) { // 并发读取 url const textPromises = urls.map(async url => { const response = await fetch(url); return response.text(); }); // 按次序输出 for (const textPromise of textPromises) { console.log(await textPromise); } }
Um die Erfassung dieser Art von Fehlern zu vereinfachen, können wir das Versprechen danach geben „await Object“ fügt eine Catch-Funktion hinzu, für die wir einen Helfer schreiben müssen:
async function asyncTask(cb) { try { const user = await UserModel.findById(1); if(!user) return cb('No user found'); } catch(e) { return cb('Unexpected error occurred'); } try { const savedTask = await TaskModel({userId: user.id, name: 'Demo Task'}); } catch(e) { return cb('Error occurred while saving task'); } if(user.notificationsEnabled) { try { await NotificationService.sendNotification(user.id, 'Task Created'); } catch(e) { return cb('Error while sending notification'); } } if(savedTask.assignedUser.id !== user.id) { try { await NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'); } catch(e) { return cb('Error while sending notification'); } } cb(null, savedTask); }
Der gesamte Fehlerabfangcode kann wie folgt vereinfacht werden:
// to.js export default function to(promise) { return promise.then(data => { return [null, data]; }) .catch(err => [err]); }
Generator wird ursprünglich als Generator verwendet, um asynchrone Anforderungen zu verarbeiten. In Bezug auf Asynchronität kann Async Generator ersetzen, aber die beiden Syntaxen Async und Generator werden verwendet, um unterschiedliche Probleme zu lösen. von.
Die asynchrone Funktion gibt ein Promise-Objekt zurück
Angesichts komplexer asynchroner Prozesse sind die von Promise bereitgestellten All- und Race-Funktionen nützlicher
Promise selbst ist ein Objekt, daher kann es beliebig im Code übergeben werden
Die Unterstützungsrate von Async ist immer noch sehr niedrig Bei Babel müssen nach der Kompilierung etwa 1000 Zeilen hinzugefügt werden.
Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in Async-Funktionen in ES6 (mit Beispielen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!