Maison  >  Article  >  interface Web  >  Les tenants et aboutissants de async/await

Les tenants et aboutissants de async/await

hzc
hzcavant
2020-06-15 09:53:162686parcourir

Avant-propos

Lors de l’entretien, async/wait est un bon indicateur des connaissances du candidat. Bien sûr, je n'ai pas réfléchi à quel angle expliquer ce point de connaissance. Lorsque l'intervieweur vous le demande, vous pouvez répondre au sucre syntaxique du générateur auto-exécutable. Mais est-ce que je m'en suis un peu rendu compte, ou ai-je vu sa réalisation ?

Comment Babel est implémenté

Remarque : si vous ne connaissez pas le générateur, vous pouvez d'abord jeter un œil au générateur, et en passant, à l'itérateur.

ex code :

async function t() {
    const x = await getResult();
  	const y = await getResult2();
  	return x + y;
}

code de conversion babel

"use strict";

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}

function _asyncToGenerator(fn) {
    return function () {
        var self = this, args = arguments;
        return new Promise(function (resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}

function t() {
  return _t.apply(this, arguments);
}

function _t() {
  _t = _asyncToGenerator(function* () {
    const x = yield getResult();
    const y = yield getResult2();
    return x + y;
  });
  return _t.apply(this, arguments);
}

Comme le montre le code, il faut deux étapes à babel pour convertir un generator en un async _asyncToGenerator et asyncGeneratorStep.

Qu'a fait _asyncToGenerator ?

1. L'appel _asyncToGenerator a renvoyé un promise, qui correspond exactement aux caractéristiques auxquelles la fonction async peut être connectée <.>. then

2. Définir une méthode réussie

et définir une méthode échouée _next. Dans les deux fonctions, _throw est appelé. Après avoir lu asyncGeneratorStep, vous saurez qu'il s'agit en fait d'une récursion. asyncGeneratorStep

3. Exécuter

. Il s'agit du générateur auto-exécutable mentionné ci-dessus. _next

Qu'a-t-il faitasyncGeneratorStep

1. Try-catch pour capturer les erreurs lors de l'exécution de

. Si une erreur est signalée, la fonction generator entre directement dans le statut async. reject

2. Déterminez si la valeur

dans info est vraie, cela signifie que l'itérateur a été exécuté et que la valeur done peut être transmise. Sinon, continuez à appeler resolve pour transmettre la valeur au suivant. _next

这里我唯一没有看明白的是`_throw`,这个看代码像是执行不到的。promise.resolve状态值应该是fulfilled。看懂的
可以在评论中和我说一下,感谢。

Avantages de async/await

Chaque fois qu'un nouveau sucre syntaxique apparaît, il doit compenser les défauts de la solution de la génération précédente.

ex : L'émergence de

promesse est d'éviter

La manière de l'éviter est d'enchaîner les appels. callback hell

Que résout async/await ?


La nécessité de remplacer les promesses par async/await

La manière synchrone de gérer les

async/await asynchrones est plus proche du style de synchronisation, tandis que la promesse utilise la méthode then. Par rapport à async/await, le code deviendra plus grand, et il n'y a pas beaucoup de différence entre les fonctions async/await et de synchronisation. Cependant, il y a encore une lacune dans la méthode d'écriture de la promesse.

Comparaison des codes de promesse et asynchrone/attente

version promise

function getData() {
    getRes().then((res) => {
        console.log(res);
    })
}

version async/await

const getData = async function() {
    const res = await getRes();
    console.log(res);
}

Valeur intermédiaire

Lorsque vous utilisez des promesses, vous constaterez que lorsque plusieurs promesses sont sérialisées, il est très difficile pour la promesse suivante d'obtenir la valeur de la promesse précédente. Et async résout exactement ce problème.

Exemple de promesse d'obtenir une valeur intermédiaire

const morePromise = () => {
	return promiseFun1().then((value1) => {
		return promiseFun2(value1).then((value2) => {
			return promiseFun3(value1, value2).then((res) => {
				console.log(res);
			})
		}) 
	})
}

Ce qui précède est une version imbriquée, qui peut ne pas être imbriquée en fonction des différents besoins.

const morePromise = () => {
	return promiseFun1().then((value1) => {
		return promiseAll([value1, promiseFun2(value1)])
	}).then(([value1, value2]) => {
		return promiseFun3(value1, value2).then((res) => {
			console.log(res);
		})
	})
}

Moins de niveaux de nidification, mais toujours pas satisfaisant.

Utilisation d'un exemple d'optimisation async/await

const morePromise = async function() {
	const value1 = await promiseFun1();
	const value2 = await promiseFun2(value1);
	const res = await promiseFun3(value1, valuw2);
	return res;
}

Les processus asynchrones en série doivent impliquer des valeurs intermédiaires, les avantages de async/await sont donc évidents.

Situation de déclaration conditionnelle

Par exemple, il existe actuellement une exigence. Après avoir demandé une donnée, vous pouvez alors déterminer si vous devez demander plus de données. Il y aura toujours des niveaux imbriqués lors de la mise en œuvre à l'aide de promesses.

const a = () => {
    return getResult().then((data) => {
        if(data.hasMore) {
            return getMoreRes(data).then((dataMore) => {
                return dataMore;
            })
        } else {
            return data;
        }
    })
}

Mais utiliser async pour optimiser cet exemple peut rendre le code plus beau.

Exemples d'optimisation async/await

const a = async() => {
    const data = await getResult();
    if(data.hasMore) {
        const dataMore = await getMoreRes(data);
        return dataMore;
    } else {
        return data;
    }
}

Inconvénients de async/await

Nous avons parlé de certains des avantages de async/await ci-dessus, mais async/await n'est pas omnipotent . Ce qui précède concerne tous les scénarios asynchrones en série. Quand on se transforme en un scénario asynchrone parallèle. Il est encore nécessaire d'utiliser promise.all pour implémenter des

scénarios asynchrones parallèles

const a = async function() {
    const res = await Promise.all[getRes1(), getRes2()];
    return res;
}

gestion des erreurs async/await

async/await dans la capture d'erreurs L'aspect principal est le try-catch.

try-catch

const a = async () => {
    try{
        const res = await Promise.reject(1);
    } catch(err) {
        console.log(err);
    }
}

promise's catch

peut extraire une fonction publique pour ce faire. Étant donné que chaque promesse est suivie d'un traitement catch, le code sera très long.

const a = async function() {
    const res = await Promise.reject(1).catch((err) => {
        console.log(err);
    })
}
rrree

Tutoriel recommandé : "

Tutoriel JS"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer