Maison  >  Article  >  interface Web  >  Explication détaillée de la façon d'utiliser la fonction asynchrone dans js

Explication détaillée de la façon d'utiliser la fonction asynchrone dans js

php中世界最好的语言
php中世界最好的语言original
2018-05-22 09:44:584063parcourir

Cette fois, je vais vous apporter une explication détaillée de la façon d'utiliser les fonctions asynchrones en js. Quelles sont les précautions lors de l'utilisation des fonctions asynchrones en js. Voici des cas pratiques, jetons un coup d'œil.

1. La solution ultime

Le fonctionnement asynchrone est une chose gênante dans la programmation JavaScript C'est tellement gênant que certaines personnes en proposent diverses. solutions et essayer de résoudre ce problème.

De la première fonction de rappel à l'objet Promise, puis à la fonction Générateur, il y a eu des améliorations à chaque fois, mais cela semble incomplet. Ils présentent tous des complexités supplémentaires et nécessitent une compréhension des mécanismes de fonctionnement sous-jacents de l’abstraction.

Les E/S asynchrones ne se limitent-elles pas à lire un fichier ? Pourquoi cela doit-il être si compliqué ? L'état le plus élevé de la programmation asynchrone est que vous n'avez pas du tout à vous soucier de savoir si elle est asynchrone.

Les fonctions asynchrones sont la lumière au bout du tunnel, et beaucoup de gens les considèrent comme la solution ultime pour les opérations asynchrones.

2. Qu'est-ce que la fonction asynchrone ?

En un mot, la fonction asynchrone est le sucre syntaxique de la fonction Générateur.

Il y a une fonction Générateur dans l'article précédent, qui lit deux fichiers en séquence.

var fs = require('fs');
var readFile = function (fileName){
 return new Promise(function (resolve, reject){
  fs.readFile(fileName, function(error, data){
   if (error) reject(error);
   resolve(data);
  });
 });
};
var gen = function* (){
 var f1 = yield readFile('/etc/fstab');
 var f2 = yield readFile('/etc/shells');
 console.log(f1.toString());
 console.log(f2.toString());
};

est écrit comme une fonction asynchrone, comme suit.

var asyncReadFile = async function (){
 var f1 = await readFile('/etc/fstab');
 var f2 = await readFile('/etc/shells');
 console.log(f1.toString());
 console.log(f2.toString());
};

Après comparaison, vous constaterez que la fonction async consiste à remplacer l'astérisque (*) de la fonction Generator par async, et à remplacer rendement par wait, et c'est tout.

3. Avantages de la fonction asynchrone

Les améliorations de la fonction asynchrone par rapport à la fonction Générateur se reflètent dans les trois points suivants.

(1) Actionneur intégré. L'exécution de la fonction Generator doit reposer sur l'exécuteur, il existe donc la bibliothèque de fonctions co, et la fonction async est livrée avec son propre exécuteur. En d’autres termes, l’exécution des fonctions asynchrones est exactement la même que celle des fonctions ordinaires, avec une seule ligne.

var result = asyncReadFile();

(2) Meilleure sémantique. Async et wait ont une sémantique plus claire que l'astérisque et le rendement. async signifie qu'il y a une opération asynchrone dans la fonction, et wait signifie que l' expression suivante doit attendre le résultat.

(3) Applicabilité plus large. Selon la convention de la bibliothèque de fonctions co, la commande rendement ne peut être suivie que d'une fonction Thunk ou d'un objet Promise, tandis que la commande wait de la fonction async peut être suivie d'un objet Promise et de valeurs de type primitif (valeurs numériques , chaînes et valeurs booléennes, mais cela équivaut à une opération synchrone).

4. Implémentation de la fonction asynchrone

L'implémentation de la fonction asynchrone consiste à envelopper la fonction Générateur et l'exécuteur automatique dans une fonction.

async function fn(args){
 // ...
}
// 等同于
function fn(args){ 
 return spawn(function*() {
  // ...
 }); 
}

Toutes les fonctions asynchrones peuvent être écrites sous la deuxième forme ci-dessus, où la fonction spawn est l'exécuteur automatique.

L'implémentation de la fonction spawn est donnée ci-dessous, qui est essentiellement une réplique de l'exécuteur automatique précédent.

function spawn(genF) {
 return new Promise(function(resolve, reject) {
  var gen = genF();
  function step(nextF) {
   try {
    var next = nextF();
   } catch(e) {
    return reject(e); 
   }
   if(next.done) {
    return resolve(next.value);
   } 
   Promise.resolve(next.value).then(function(v) {
    step(function() { return gen.next(v); });   
   }, function(e) {
    step(function() { return gen.throw(e); });
   });
  }
  step(function() { return gen.next(undefined); });
 });
}

La fonction async est une toute nouvelle fonctionnalité de syntaxe, si nouvelle qu'elle n'appartient pas à ES6, mais à ES7. Actuellement, il est encore au stade de proposition, mais les transcodeurs Babel et régénérateur le prennent déjà en charge et peuvent être utilisés après le transcodage.

5. Utilisation de la fonction asynchrone

Identique à la fonction Générateur, la fonction asynchrone renvoie un objet Promise, et vous pouvez utiliser le then méthode pour ajouter une fonction de rappel. Lorsque la fonction est exécutée, une fois qu'elle rencontre wait, elle reviendra d'abord, attendra que l'opération asynchrone déclenchée soit terminée, puis exécutera les instructions suivantes dans le corps de la fonction.

Voici un exemple.

async function getStockPriceByName(name) {
 var symbol = await getStockSymbol(name);
 var stockPrice = await getStockPrice(symbol);
 return stockPrice;
}
getStockPriceByName('goog').then(function (result){
 console.log(result);
});

Le code ci-dessus est une fonction permettant d'obtenir des cotations boursières. Le mot-clé async devant la fonction indique qu'il y a des opérations asynchrones à l'intérieur de la fonction. Lorsque cette fonction est appelée, un objet Promise est renvoyé immédiatement.

L'exemple suivant génère une valeur après avoir spécifié le nombre de millisecondes.

function timeout(ms) {
 return new Promise((resolve) => {
  setTimeout(resolve, ms);
 });
}
async function asyncPrint(value, ms) {
 await timeout(ms);
 console.log(value)
}
asyncPrint('hello world', 50);

Le code ci-dessus précise qu'après 50 millisecondes, "hello world" sera affiché.

6. Notes

L'objet Promise derrière la commande wait peut être rejeté, il est donc préférable de mettre la commande wait en try ... attraper le bloc de code.

async function myFunction() {
 try {
  await somethingThatReturnsAPromise();
 } catch (err) {
  console.log(err);
 }
}
// 另一种写法
async function myFunction() {
 await somethingThatReturnsAPromise().catch(function (err){
  console.log(err);
 });
}

La commande wait ne peut être utilisée que dans les fonctions asynchrones. Si elle est utilisée dans des fonctions ordinaires, une erreur sera signalée.

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 // 报错
 docs.forEach(function (doc) {
  await db.post(doc);
 });
}

上面代码会报错,因为 await 用在普通函数之中了。但是,如果将 forEach 方法的参数改成 async 函数,也有问题。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 // 可能得到错误结果
 docs.forEach(async function (doc) {
  await db.post(doc);
 });
}

上面代码可能不会正常工作,原因是这时三个 db.post 操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用 for 循环。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 for (let doc of docs) {
  await db.post(doc);
 }
}

如果确实希望多个请求并发执行,可以使用 Promise.all 方法。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 let promises = docs.map((doc) => db.post(doc));
 let results = await Promise.all(promises);
 console.log(results);
}
// 或者使用下面的写法
async function dbFuc(db) {
 let docs = [{}, {}, {}];
 let promises = docs.map((doc) => db.post(doc));
 let results = [];
 for (let promise of promises) {
  results.push(await promise);
 }
 console.log(results);
}

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

推荐阅读:

Nodejs内存治理步骤详解

Vue页面骨架屏注入步骤详解

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