Heim > Web-Frontend > js-Tutorial > Hauptteil

Detaillierte Einführung in Async-Funktionen in ES6 (mit Beispielen)

不言
Freigeben: 2018-10-24 10:33:49
nach vorne
2703 Leute haben es durchsucht

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.

async

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);
Nach dem Login kopieren

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();
Nach dem Login kopieren

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* () {
    // ...
  });
}
Nach dem Login kopieren

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.

Async und Promise

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.

1. Der Code ist prägnanter

/**
 * 示例一
 */
function fetch() {
  return (
    fetchData()
    .then(() => {
      return "done"
    });
  )
}

async function fetch() {
  await fetchData()
  return "done"
};
Nach dem Login kopieren
/**
 * 示例二
 */
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
  }
};
Nach dem Login kopieren

2. Fehlerbehandlung

/**
 * 示例三
 */
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)
};
Nach dem Login kopieren

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)
  }
}
Nach dem Login kopieren

Das Aufkommen von async/await ermöglicht es Try/Catch, synchrone und asynchrone Fehler zu erfassen.

3. Debuggen

async function fetch() {
  try {
    const data = JSON.parse(await fetchData())
  } catch (err) {
    console.log(err)
  }
};
Nach dem Login kopieren

Detaillierte Einführung in Async-Funktionen in ES6 (mit Beispielen)

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);
Nach dem Login kopieren

Detaillierte Einführung in Async-Funktionen in ES6 (mit Beispielen)

Wenn Sie Async verwenden, können Sie es genauso debuggen wie synchronen Code debuggen.

asynchrone Hölle

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...

Beispiel 1

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);
Nach dem Login kopieren

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();
})();
Nach dem Login kopieren

Sie können auch Promise.all() verwenden:

(async () => {
  const listPromise = getList();
  const anotherListPromise = getAnotherList();
  await listPromise;
  await anotherListPromise;
})();
Nach dem Login kopieren

Beispiel 2

Natürlich ist das obige Beispiel relativ einfach, erweitern wir es:

(async () => {
  Promise.all([getList(), getAnotherList()]).then(...);
})();
Nach dem Login kopieren

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

})();
Nach dem Login kopieren

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)
}
Nach dem Login kopieren

Nachfolge und Parallelität

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()
})()
Nach dem Login kopieren
// 继发一
async function loadData() {
  var res1 = await fetch(url1);
  var res2 = await fetch(url2);
  var res3 = await fetch(url3);
  return "whew all done";
}
Nach dem Login kopieren

asynchrone gleichzeitige Implementierung:

// 继发二
async function loadData(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
Nach dem Login kopieren
// 并发一
async function loadData() {
  var res = await Promise.all([fetch(url1), fetch(url2), fetch(url3)]);
  return "whew all done";
}
Nach dem Login kopieren

asynchrone Fehlererfassung

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);
  }
}
Nach dem Login kopieren

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);
}
Nach dem Login kopieren

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]);
}
Nach dem Login kopieren

Einige Diskussionen über Async

Async wird Generator ersetzen?

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.

Wird Async Promise ersetzen?

  1. Die asynchrone Funktion gibt ein Promise-Objekt zurück

  2. Angesichts komplexer asynchroner Prozesse sind die von Promise bereitgestellten All- und Race-Funktionen nützlicher

  3. Promise selbst ist ein Objekt, daher kann es beliebig im Code übergeben werden

  4. 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!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage