Maison  >  Article  >  interface Web  >  Une introduction détaillée à l'utilisation d'async et d'attente en Javascript

Une introduction détaillée à l'utilisation d'async et d'attente en Javascript

黄舟
黄舟original
2017-05-22 11:44:061813parcourir

Cet article présente principalement l'utilisation de async/awai en Javascript. Il expliquera le fonctionnement de async/await. Ceux qui sont intéressés peuvent en apprendre davantage

async/await est l'une des fonctionnalités importantes d'ES7. , qui est également reconnue comme une excellente solution asynchrone dans la communauté. À l'heure actuelle, la fonctionnalité async/wait est déjà une recommandation de niveau 3. Vous pouvez vérifier la progression de TC39. Cet article expliquera le fonctionnement d'async/wait. Avant de lire cet article, j'espère que vous avez des connaissances liées à ES6 telles que Promise, le générateur. , et le rendement.

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.

Traitement asynchrone de Promise

Bien que les E/S asynchrones de Node.js apportent un bon support pour une concurrence élevée, elles font également des "rappels" un désastre, ce qui est très facile à 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 logiques 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 réduit uniquement l'imbrication, mais n'élimine pas complètement l'imbrication. 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 !

Gestion de l'asynchronisme par le générateur

Quand il s'agit de générateurs, vous ne devriez pas être étranger à cela. 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 à python, lua, etc. Coroutines dans la langue. 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);
});

Gestion asynchrone/attente du traitement asynchrone

Bien que co soit une excellente solution asynchrone dans la communauté, ce n'est pas un standard de langage, juste 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 contient les fichiers compilés async/await dont nous avons besoin.

Que ce soit du côté du navigateur ou de Node.js, vous devez installer les packages suivants.

$ 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. 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, vous devez écrire deux fichiers, l'un est le fichier js de démarrage et l'autre est le fichier js qui exécute réellement le programme.

Démarrer le fichier 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 :

  1. async est utilisé pour déclarer que le contenu du package peut être exécuté de manière synchrone, tandis que wait contrôle la séquence d'exécution. Chaque fois qu'un wait est exécuté, le programme fera une pause et attendra la valeur de retour de wait, puis exécutera le wait suivant. .

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

  3. await ne peut être utilisé que dans des fonctions asynchrones. S'il est utilisé dans des fonctions ordinaires, une erreur sera signalée.

  4. L'objet Promise derrière la commande wait peut entraîner un 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 le code à l'intérieur peut être traité 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.

[Recommandations associées]

1. Tutoriel vidéo gratuit Javascript

2.Introduction détaillée au mouvement à valeurs multiples du framework de mouvement JavaScript. (4)

3.Exemple de partage de code de mouvement de valeurs arbitraires multi-objets dans le cadre de mouvement JavaScript (3)

4 Comment résoudre le problème d'anti-tremblement et de suspension en JavaScript. motion framework Couplet (2)

5. Comment le framework de mouvement JavaScript résout le problème de l'arrondi de vitesse positif et négatif (1)

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn