Heim Web-Frontend js-Tutorial Detaillierte Erläuterung der Schritte zum Schreiben der asynchronen js-Funktion

Detaillierte Erläuterung der Schritte zum Schreiben der asynchronen js-Funktion

May 22, 2018 am 09:49 AM
async javascript 详解

Dieses Mal werde ich Ihnen die Schritte zum Schreiben von js-asynchronen Funktionen ausführlich erläutern. Was sind die Vorsichtsmaßnahmen zum Schreiben von js-asynchronen Funktionen?

Der Mai 2018 ist da und auch die Wartung der 4.x-Version von Node wurde eingestellt. Ein bestimmter Dienst unseres Unternehmens wurde ebenfalls auf 8.x umgestellt. Wir migrieren derzeit den vorherigen Generator auf koa2.x . Ersetzen Sie alle durch Async. Während des Ersetzungsprozesses haben wir jedoch festgestellt, dass durch den Missbrauch von Async Zeit verloren geht async

Zunächst müssen Sie Promise verstehen

Promise ist die Grundlage für die Verwendung von async/await, daher müssen Sie zunächst verstehen, was Promise tut

Versprechen hilft dabei, die Callback-Hölle zu lösen. Gute Sache, macht asynchrone Prozesse klarer.

Ein einfaches Beispiel für die Konvertierung von Error-first-callback in Promise:

const fs = require('fs')
function readFile (fileName) {
 return new Promise((resolve, reject) => {
  fs.readFile(fileName, (err, data) => {
   if (err) reject(err)
   resolve(data)
  })
 })
}
readFile('test.log').then(data => {
 console.log('get data')
}, err => {
 console.error(err)
})
Nach dem Login kopieren

Wir rufen die Funktion auf, um eine Promise-Instanz zurückzugeben, und lesen die Datei während des Instanziierungsprozesses Der Rückruf wird ausgelöst, um den Promise-Status zu ändern. Wir verwenden dann, um Änderungen im gelösten oder abgelehnten Status zu überwachen. Der erste Rückruf dient der Auflösungsverarbeitung und der zweite Rückruf dient der Ablehnungsverarbeitung.

Die Beziehung zwischen Async und Promise

Die Async-Funktion entspricht einer Kurzfunktion, die eine Promise-Instanz zurückgibt. Der Effekt ist wie folgt :

function getNumber () {
 return new Promise((resolve, reject) => {
  resolve(1)
 })
}
// =>
async function getNumber () {
 return 1
}
Nach dem Login kopieren

Beide werden auf genau die gleiche Weise verwendet. Sie können then verwenden, um den Rückgabewert nach dem Aufruf der getNumber-Funktion zu überwachen. Und wie man die Async-Await-Syntax verwendet: Die Ausführung von

getNumber().then(data => {
 // got data
})
// =>
let data = await getNumber()
Nach dem Login kopieren

await erhält das Promise-Ausführungsergebnis hinter dem -Ausdruck , was unserem Aufruf von then entspricht, um das Rückrufergebnis zu erhalten . P.S. Als die Async/Await-Unterstützung nicht sehr hoch war, würde sich jeder dafür entscheiden, Generator/Yield in Kombination mit einigen Co-ähnlichen Bibliotheken zu verwenden, um ähnliche Effekte zu erzielen.

Die Ausführung des Async-Funktionscodes erfolgt synchron und das Ergebnis wird zurückgegeben asynchron

Es ist sehr wichtig, dass die asynchrone Funktion immer eine Promise-Instanz zurückgibt. Wenn Sie also eine asynchrone Funktion aufrufen, können Sie verstehen, dass sich der darin enthaltene Code in einem neuen Promise befindet und daher synchron ausgeführt wird. Die endgültige Rückgabe Die Operation entspricht dem Aufruf von „resolution“ im Versprechen:

async function getNumber () {
 console.log('call getNumber()')
 return 1
}
getNumber().then(_ => console.log('resolved'))
console.log('done')
// 输出顺序:
// call getNumber()
// done
// resolved
Nach dem Login kopieren

Das Versprechen innerhalb des Versprechens wird verdaut

das heißt, wenn wir haben den folgenden Code:

function getNumber () {
 return new Promise(resolve => {
  resolve(Promise.resolve(1))
 })
}
getNumber().then(data => console.log(data)) // 1
Nach dem Login kopieren

Wenn wir dem oben Gesagten folgen, sollten die Daten, die wir dann erhalten, der Wert sein, der an „resolve“ übergeben wird, was eine weitere Promise-Instanz ist.
Tatsächlich erhalten wir jedoch den Rückgabewert direkt: 1. Das heißt, wenn wir ein Promise in Promise zurückgeben, hilft uns das Programm tatsächlich bei der Ausführung dieses Promises und löst dann einen Rückruf aus, wenn sich der interne Promise-Status ändert .
Eine interessante Sache:

function getNumber () {
 return new Promise(resolve => {
  resolve(Promise.reject(new Error('Test')))
 })
}
getNumber().catch(err => console.error(err)) // Error: Test
Nach dem Login kopieren

Wenn wir eine Ablehnung in Resolution übergeben, können wir Catch direkt verwenden, um es extern zu überwachen.
Diese Methode wird oft verwendet, um Ausnahmen in asynchronen Funktionen auszulösen So lösen Sie Ausnahmen in asynchronen Funktionen aus:

async function getNumber () {
 return Promise.reject(new Error('Test'))
}
try {
 let number = await getNumber()
} catch (e) {
 console.error(e)
}
Nach dem Login kopieren

Achten Sie darauf, die Schlüsselwörter „await“ nicht zu vergessen

Wenn Sie vergessen, das Schlüsselwort „await“ hinzuzufügen, wird auf Codeebene kein Fehler gemeldet, aber der Rückgabewert, den wir erhalten, ist ein Versprechen

let number = getNumber()
console.log(number) // Promise
Nach dem Login kopieren

, also sei so Verwenden Sie es unbedingt. Denken Sie daran, dass das Schlüsselwort „await“

let number = await getNumber()
console.log(number) // 1
Nach dem Login kopieren
Nach dem Login kopieren

nicht überall hinzugefügt werden muss.

Während der Ausführung des Codes müssen manchmal nicht alle asynchronen Vorgänge „await“ hinzufügen. Zum Beispiel die folgende Dateioperation:

Wir gehen davon aus, dass alle fs-APIs von uns in Promise-Versionen konvertiert wurden

let number = await getNumber()
console.log(number) // 1
Nach dem Login kopieren
Nach dem Login kopieren

Wir öffnen eine Datei über „await“ und schreiben die Datei dann zweimal.

Beachten Sie jedoch, dass wir das Schlüsselwort „await“ nicht vor den beiden Dateischreibvorgängen hinzugefügt haben.
Da dies überflüssig ist, müssen wir der API nur mitteilen, dass ich eine Textzeile in diese Datei schreiben möchte. Die Reihenfolge wird natürlich von fs gesteuert.
Dann verwenden wir „await“, um die Datei am Ende zu schließen .
Denn wenn wir den obigen Schreibvorgang ausführen, wird der Close-Callback nicht ausgelöst.
Mit anderen Worten: Das Auslösen des Callbacks bedeutet, dass die beiden oben genannten Schreibschritte abgeschlossen sind.

合并多个不相干的async函数调用

如果我们现在要获取一个用户的头像和用户的详细信息(而这是两个接口 虽说一般情况下不太会出现)

async function getUser () {
 let avatar = await getAvatar()
 let userInfo = await getUserInfo()
 return {
  avatar,
  userInfo
 }
}
Nach dem Login kopieren

这样的代码就造成了一个问题,我们获取用户信息的接口并不依赖于头像接口的返回值。
 但是这样的代码却会在获取到头像以后才会去发送获取用户信息的请求。
 所以我们对这种代码可以这样处理:

async function getUser () {
 let [avatar, userInfo] = await Promise.all([getAvatar(), getUserInfo()])
 return {
  avatar,
  userInfo
 }
}
Nach dem Login kopieren

这样的修改就会让getAvatar与getUserInfo内部的代码同时执行,同时发送两个请求,在外层通过包一层Promise.all来确保两者都返回结果。

让相互没有依赖关系的异步函数同时执行

一些循环中的注意事项

forEach

当我们调用这样的代码时:

async function getUsersInfo () {
 [1, 2, 3].forEach(async uid => {
  console.log(await getUserInfo(uid))
 })
}
function getuserInfo (uid) {
 return new Promise(resolve => {
  setTimeout(_ => resolve(uid), 1000)
 })
}
await getUsersInfo()
Nach dem Login kopieren

这样的执行好像并没有什么问题,我们也会得到1、2、3三条log的输出,但是当我们在await getUsersInfo()下边再添加一条console.log('done')的话,就会发现:

 我们会先得到done,然后才是三条uid的log,也就是说,getUsersInfo返回结果时,其实内部Promise并没有执行完。
 这是因为forEach并不会关心回调函数的返回值是什么,它只是运行回调。

不要在普通的for、while循环中使用await

使用普通的for、while循环会导致程序变为串行:

for (let uid of [1, 2, 3]) {
 let result = await getUserInfo(uid)
}
Nach dem Login kopieren

这样的代码运行,会在拿到uid: 1的数据后才会去请求uid: 2的数据

--------------------------------------------------------------------------------

关于这两种问题的解决方案:

目前最优的就是将其替换为map结合着Promise.all来实现:

await Promise.all([1, 2, 3].map(async uid => await getUserInfo(uid)))
Nach dem Login kopieren
Nach dem Login kopieren

这样的代码实现会同时实例化三个Promise,并请求getUserInfo

P.S. 草案中有一个await*,可以省去Promise.all

await Promise.all([1, 2, 3].map(async uid => await getUserInfo(uid)))
Nach dem Login kopieren
Nach dem Login kopieren

P.S. 为什么在使用Generator+co时没有这个问题

在使用koa1.x的时候,我们直接写yield [].map是不会出现上述所说的串行问题的看过co源码的小伙伴应该都明白,里边有这么两个函数(删除了其余不相关的代码):

function toPromise(obj) {
 if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
 return obj;
}
function arrayToPromise(obj) {
 return Promise.all(obj.map(toPromise, this));
}
Nach dem Login kopieren

co是帮助我们添加了Promise.all的处理的(膜拜TJ大佬)。

总结

总结一下关于async函数编写的几个小提示:

1.使用return Promise.reject()在async函数中抛出异常
2.让相互之间没有依赖关系的异步函数同时执行
3.不要在循环的回调中/for、while循环中使用await,用map来代替它

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

js中async函数使用方法详解

node搭建服务器,写接口,调接口,跨域方法详解

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Schritte zum Schreiben der asynchronen js-Funktion. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Ausführliche Erklärung zur Erlangung von Administratorrechten in Win11 Ausführliche Erklärung zur Erlangung von Administratorrechten in Win11 Mar 08, 2024 pm 03:06 PM

Das Windows-Betriebssystem ist eines der beliebtesten Betriebssysteme der Welt und seine neue Version Win11 hat viel Aufmerksamkeit erregt. Im Win11-System ist die Erlangung von Administratorrechten ein wichtiger Vorgang. Mit Administratorrechten können Benutzer weitere Vorgänge und Einstellungen auf dem System durchführen. In diesem Artikel wird ausführlich beschrieben, wie Sie Administratorrechte im Win11-System erhalten und wie Sie Berechtigungen effektiv verwalten. Im Win11-System werden Administratorrechte in zwei Typen unterteilt: lokaler Administrator und Domänenadministrator. Ein lokaler Administrator verfügt über vollständige Administratorrechte für den lokalen Computer

Detaillierte Erläuterung der Divisionsoperation in Oracle SQL Detaillierte Erläuterung der Divisionsoperation in Oracle SQL Mar 10, 2024 am 09:51 AM

Detaillierte Erläuterung der Divisionsoperation in OracleSQL In OracleSQL ist die Divisionsoperation eine häufige und wichtige mathematische Operation, die zur Berechnung des Ergebnisses der Division zweier Zahlen verwendet wird. Division wird häufig in Datenbankabfragen verwendet. Daher ist das Verständnis der Divisionsoperation und ihrer Verwendung in OracleSQL eine der wesentlichen Fähigkeiten für Datenbankentwickler. In diesem Artikel werden die relevanten Kenntnisse über Divisionsoperationen in OracleSQL ausführlich erörtert und spezifische Codebeispiele als Referenz für die Leser bereitgestellt. 1. Divisionsoperation in OracleSQL

Detaillierte Erläuterung der Rolle und Verwendung des PHP-Modulo-Operators Detaillierte Erläuterung der Rolle und Verwendung des PHP-Modulo-Operators Mar 19, 2024 pm 04:33 PM

Der Modulo-Operator (%) in PHP wird verwendet, um den Rest der Division zweier Zahlen zu ermitteln. In diesem Artikel werden wir die Rolle und Verwendung des Modulo-Operators im Detail besprechen und spezifische Codebeispiele bereitstellen, um den Lesern ein besseres Verständnis zu erleichtern. 1. Die Rolle des Modulo-Operators Wenn wir in der Mathematik eine ganze Zahl durch eine andere ganze Zahl dividieren, erhalten wir einen Quotienten und einen Rest. Wenn wir beispielsweise 10 durch 3 dividieren, ist der Quotient 3 und der Rest ist 1. Um diesen Rest zu ermitteln, wird der Modulo-Operator verwendet. 2. Verwendung des Modulo-Operators In PHP verwenden Sie das %-Symbol, um den Modul darzustellen

Detaillierte Erläuterung der Funktion system() des Linux-Systemaufrufs Detaillierte Erläuterung der Funktion system() des Linux-Systemaufrufs Feb 22, 2024 pm 08:21 PM

Detaillierte Erläuterung der Funktion system() des Linux-Systems Der Systemaufruf ist ein sehr wichtiger Teil des Linux-Betriebssystems. Er bietet eine Möglichkeit, mit dem Systemkernel zu interagieren. Unter diesen ist die Funktion system() eine der am häufigsten verwendeten Systemaufruffunktionen. In diesem Artikel wird die Verwendung der Funktion system() ausführlich vorgestellt und entsprechende Codebeispiele bereitgestellt. Grundlegende Konzepte von Systemaufrufen Systemaufrufe sind eine Möglichkeit für Benutzerprogramme, mit dem Betriebssystemkernel zu interagieren. Benutzerprogramme fordern das Betriebssystem an, indem sie Systemaufruffunktionen aufrufen

Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Jan 05, 2024 pm 06:08 PM

JavaScript-Tutorial: So erhalten Sie HTTP-Statuscode. Es sind spezifische Codebeispiele erforderlich. Vorwort: Bei der Webentwicklung ist häufig die Dateninteraktion mit dem Server erforderlich. Bei der Kommunikation mit dem Server müssen wir häufig den zurückgegebenen HTTP-Statuscode abrufen, um festzustellen, ob der Vorgang erfolgreich ist, und die entsprechende Verarbeitung basierend auf verschiedenen Statuscodes durchführen. In diesem Artikel erfahren Sie, wie Sie mit JavaScript HTTP-Statuscodes abrufen und einige praktische Codebeispiele bereitstellen. Verwenden von XMLHttpRequest

Detaillierte Erläuterung des Linux-Befehls „curl'. Detaillierte Erläuterung des Linux-Befehls „curl'. Feb 21, 2024 pm 10:33 PM

Detaillierte Erläuterung des Linux-Befehls „curl“ Zusammenfassung: Curl ist ein leistungsstarkes Befehlszeilentool für die Datenkommunikation mit dem Server. In diesem Artikel wird die grundlegende Verwendung des Curl-Befehls vorgestellt und tatsächliche Codebeispiele bereitgestellt, um den Lesern zu helfen, den Befehl besser zu verstehen und anzuwenden. 1. Was ist Locken? Curl ist ein Befehlszeilentool zum Senden und Empfangen verschiedener Netzwerkanfragen. Es unterstützt mehrere Protokolle wie HTTP, FTP, TELNET usw. und bietet umfangreiche Funktionen wie Datei-Upload, Datei-Download, Datenübertragung und Proxy

Erfahren Sie mehr über Promise.resolve() Erfahren Sie mehr über Promise.resolve() Feb 18, 2024 pm 07:13 PM

Eine detaillierte Erklärung von Promise.resolve() erfordert spezifische Codebeispiele. Promise ist ein Mechanismus in JavaScript zur Verarbeitung asynchroner Vorgänge. In der tatsächlichen Entwicklung ist es häufig erforderlich, einige asynchrone Aufgaben zu verarbeiten, die nacheinander ausgeführt werden müssen, und die Methode Promise.resolve () wird verwendet, um ein erfülltes Promise-Objekt zurückzugeben. Promise.resolve() ist eine statische Methode der Promise-Klasse, die a akzeptiert

Detaillierte Analyse der C-Sprachlernroute Detaillierte Analyse der C-Sprachlernroute Feb 18, 2024 am 10:38 AM

Als weit verbreitete Programmiersprache im Bereich der Softwareentwicklung ist die Sprache C für viele Programmieranfänger die erste Wahl. Das Erlernen der C-Sprache kann uns nicht nur dabei helfen, grundlegende Programmierkenntnisse zu erwerben, sondern auch unsere Problemlösungs- und Denkfähigkeiten verbessern. In diesem Artikel wird eine Roadmap zum Erlernen der C-Sprache im Detail vorgestellt, um Anfängern dabei zu helfen, ihren Lernprozess besser zu planen. 1. Grundlegende Grammatik lernen Bevor wir mit dem Erlernen der C-Sprache beginnen, müssen wir zunächst die grundlegenden Grammatikregeln der C-Sprache verstehen. Dazu gehören Variablen und Datentypen, Operatoren, Steueranweisungen (z. B. if-Anweisungen,

See all articles