Maison  >  Article  >  interface Web  >  Explication détaillée du fonctionnement de async/await en Javascript

Explication détaillée du fonctionnement de async/await en Javascript

青灯夜游
青灯夜游avant
2021-01-13 18:46:161845parcourir

Explication détaillée du fonctionnement de async/await en Javascript

Recommandations associées : "Tutoriel vidéo javascript"

async/await est l'une des fonctionnalités importantes d'ES7 et est actuellement reconnu comme excellent dans la solution communautaire Asynchrone. Actuellement, la fonctionnalité async/await est déjà une recommandation pour l'étape 3. Vous pouvez consulter la progression du TC39 Cet article expliquera comment fonctionne async/await avant de lire ceci. article, j'espère que vous avez des connaissances pertinentes sur Promise, Generator, Yield et autres ES6.

Avant de présenter async/await en détail, passons en revue les meilleures méthodes de traitement asynchrone actuelles dans ES6. Dans l'exemple suivant, la demande de données utilise le module de requête dans Node.js et l'interface de données utilise l'API de détails du référentiel de code de dépôt fournie par le document API Github v3 comme exemple de démonstration.

Gestion de l'asynchrone par Promise

Bien que les entrées/sorties asynchrones de Node.js apportent un bon support pour une concurrence élevée, elles font également des "rappels" un désastre et peuvent facilement provoquer un enfer de rappel. Les méthodes traditionnelles, telles que l'utilisation de fonctions nommées, peuvent réduire le nombre de niveaux d'imbrication et rendre le code plus clair. Cependant, cela entraînera une mauvaise expérience de codage et de débogage. Vous devez souvent utiliser ctrl + f pour trouver la définition d'une fonction nommée, ce qui fait sauter fréquemment la fenêtre de l'IDE. Après avoir utilisé Promise, le nombre de niveaux d'imbrication peut être très bien réduit. De plus, l'implémentation de Promise utilise une machine à états et le processus peut être bien contrôlé via la résolution et le rejet dans la fonction. Vous pouvez exécuter une série de logique de code dans une chaîne séquentielle. Voici un exemple d'utilisation de Promise :

const request = require('request');
// 请求的url和header
const options = {
  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
  headers: {
    'User-Agent': 'request'
  }
};
// 获取仓库信息
const getRepoData = () => {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) {
        reject(err);
      }
      resolve(body);
    });
  });
};

getRepoData()
  .then((result) => console.log(result);)
  .catch((reason) => console.error(reason););

// 此处如果是多个Promise顺序执行的话,如下:
// 每个then里面去执行下一个promise
// getRepoData()
//   .then((value2) => {return promise2})
//   .then((value3) => {return promise3})
//   .then((x) => console.log(x))

Cependant, Promise présente encore des défauts. Il ne fait que réduire l'imbrication, mais ne l'élimine pas complètement. Par exemple, lorsque plusieurs promesses sont exécutées en série, une fois la logique de la première promesse exécutée, nous devons exécuter la deuxième promesse dans sa fonction then, ce qui créera une couche d'imbrication. De plus, le code utilisant Promise semble toujours asynchrone. Ce serait formidable si le code écrit pouvait devenir synchrone !

Traitement asynchrone du générateur

Quand il s'agit de générateur, vous ne devriez pas le connaître. Pour le traitement des rappels dans Node.js, le TJ / Co que nous utilisons souvent est implémenté à l'aide d'un générateur combiné avec promise Co est l'abréviation de coroutine, qui est empruntée aux coroutines dans des langages tels que python et lua. . Il peut écrire une logique de code asynchrone de manière synchrone, ce qui rend la lecture et l'organisation du code plus claires et plus faciles à déboguer.

const co = require('co');
const request = require('request');

const options = {
  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
  headers: {
    'User-Agent': 'request'
  }
};
// yield后面是一个生成器 generator
const getRepoData = function* () {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) {
        reject(err);
      }
      resolve(body);
    });
  });
};

co(function* () {
  const result = yield getRepoData;
  // ... 如果有多个异步流程,可以放在这里,比如
  // const r1 = yield getR1;
  // const r2 = yield getR2;
  // const r3 = yield getR3;
  // 每个yield相当于暂停,执行yield之后会等待它后面的generator返回值之后再执行后面其它的yield逻辑。
  return result;
}).then(function (value) {
  console.log(value);
}, function (err) {
  console.error(err.stack);
});

Traitement asynchrone/attente de l'asynchrone

Bien que co soit une excellente solution asynchrone dans la communauté, ce n'est pas un standard de langage, mais une solution de transition. Le niveau de langage ES7 fournit une synchronisation/attente pour résoudre les problèmes de niveau de langage. Actuellement, async / wait peut être utilisé directement dans IE Edge, mais Chrome et Node.js ne le prennent pas encore en charge. Heureusement, babel prend déjà en charge la transformation asynchrone, il nous suffit donc d'introduire babel lors de son utilisation. Avant de commencer, nous devons introduire le package suivant Preset-stage-3 contenant les fichiers compilés async/await dont nous avons besoin.

Les packages suivants doivent être installés du côté du navigateur et de Node.js.

$ npm install babel-core --save
$ npm install babel-preset-es2015 --save
$ npm install babel-preset-stage-3 --save

Il est recommandé d'utiliser la méthode require hook officiellement fournie par babel. Autrement dit, après avoir entré via require, les fichiers suivants seront traités par Babel lorsque cela sera nécessaire. Parce que nous savons que CommonJs est une dépendance de module synchrone, c'est également une méthode réalisable. À ce stade, deux fichiers doivent être écrits, l'un est le fichier js de démarrage et l'autre est le fichier js qui exécute réellement le programme.

Fichier de démarrage index.js

require('babel-core/register');
require('./async.js');

async.js qui exécute réellement le programme

const request = require('request');

const options = {
  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
  headers: {
    'User-Agent': 'request'
  }
};

const getRepoData = () => {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) {
        reject(err);
      }
      resolve(body);
    });
  });
};

async function asyncFun() {
 try {
    const value = await getRepoData();
    // ... 和上面的yield类似,如果有多个异步流程,可以放在这里,比如
    // const r1 = await getR1();
    // const r2 = await getR2();
    // const r3 = await getR3();
    // 每个await相当于暂停,执行await之后会等待它后面的
    //函数(不是generator)返回值之后再执行后面其它的await逻辑。
    return value;
  } catch (err) {
    console.log(err);
  }
}

asyncFun().then(x => console.log(`x: ${x}`)).catch(err => console.error(err));

Remarque :

  • async est utilisé pour déclarer le paquet à l'intérieur Le contenu peut être exécuté de manière synchrone et wait contrôle la séquence d'exécution. Chaque fois qu'une wait est exécutée, le programme fera une pause et attendra la valeur de retour de l'attente, puis exécutera l'attente suivante.
  • La fonction appelée après wait doit renvoyer une promesse. De plus, cette fonction peut être une fonction ordinaire, pas un générateur.
  • await ne peut être utilisé que dans des fonctions asynchrones. S'il est utilisé dans des fonctions ordinaires, une erreur sera signalée.
  • L'objet Promise derrière la commande wait peut être rejeté, il est donc préférable de placer la commande wait dans le bloc de code try...catch.

En fait, l'utilisation de async/await est similaire à celle de co. wait et rendement indiquent une pause, et ils sont enveloppés d'une couche de async ou co pour indiquer que le code à l'intérieur peut. être traités de manière synchrone. Cependant, la fonction suivie de wait dans async/await ne nécessite pas de traitement supplémentaire. Co doit l'écrire en tant que générateur.

Pour plus de connaissances sur la programmation, veuillez visiter : Apprendre la programmation ! !

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