web-dev-qa-db-fra.com

Différence d'utilisation asynchrone / attente vs promesses?

Je cherche une réponse sur ce qu'il faut utiliser dans mon application nodeJS.

J'ai un code qui gère mon accès dB générique à mssql. Ce code est écrit en utilisant une fonction async puis j'ai utilisé une promesse pour appeler cette fonction et tout fonctionne bien.

Au fur et à mesure que mon application s'agrandit et que le code augmente, je prévois de déplacer une partie de la logique dans des fonctions, puis de les appeler.

Ma question est donc la suivante: y a-t-il un inconvénient à utiliser un mélange asynchrone/attente et promesses ou est-ce vraiment sans importance?

Async/Wait facilite l'écriture de code plus lisible car je dois lire et écrire sur plusieurs bases de données avant de retourner quelque chose et j'ai besoin des résultats de certaines d'entre elles.

La question est donc quelle est la meilleure approche? Asynchrone/attendre sur la couche dB qui est définie et ne peut pas changer La couche logique asynchrone/attendre qui me permettrait une asynchrone/et attendrait sur l'appel de fonction ou si je fais une promesse de logique, je suis coincé avec une promesse sur l'appel de fonction.

J'espère donc que quelqu'un pourra me donner plus d'informations si l'un a plus d'avantages que l'autre, en plus de pouvoir écrire du code plus propre.

9
MisterniceGuy

async/await Et les promesses sont étroitement liées. async les fonctions renvoient des promesses, et attendent est le sucre syntaxique pour attendre qu'une promesse soit résolue.

Le seul inconvénient d'avoir un mélange de promesses et de fonctions async peut être la lisibilité et la maintenabilité du code, mais vous pouvez certainement utiliser la valeur de retour des fonctions asynchrones comme promesses ainsi que await pour les commandes régulières fonctions qui renvoient une promesse.

Que vous choisissiez l'un ou l'autre dépend principalement de la disponibilité (votre node.js/navigateur prend-il en charge async?) Et de votre préférence esthétique, mais une bonne règle de base (basée sur ma propre préférence au moment de écrit) pourrait être:

Si vous devez exécuter du code asynchrone en série: pensez à utiliser async/await:

return asyncFunction()
.then(result => f1(result))
.then(result2 => f2(result2));

contre

const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result2);

Si vous avez besoin de promesses imbriquées: utilisez async/await:

return asyncFunction()
.then(result => {
  return f1(result)
  .then(result2 => f2(result, result2);
})

contre

const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result, result2);

Si vous devez l'exécuter en parallèle: utilisez des promesses.

return Promise.all(arrayOfIDs.map(id => asyncFn(id)))

Il a été suggéré que vous pouvez utiliser await dans une expression pour attendre plusieurs tâches comme ceci:
* note, cela attend toujours dans l'ordre de gauche à droite, ce qui est OK si vous ne vous attendez pas à des erreurs. Sinon, le comportement est différent en raison de échec du comportement rapide de Promise.all()

const [r1, r2, r3] = [await task1, await task2, await task3];
(async function() {
  function t1(t) {
    console.time(`task ${t}`);
    console.log(`start task ${t}`);
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.timeEnd(`task ${t}`);
        resolve();
      }, t);
    })
  }

  console.log('Create Promises');
  const task1 = t1(100);
  const task2 = t1(200);
  const task3 = t1(10);

  console.log('Await for each task');
  const [r1, r2, r3] = [await task1, await task2, await task3];

  console.log('Done');
}())

Mais comme avec Promise.all, Les promesses parallèles doivent être correctement gérées en cas d'erreur. Vous pouvez en savoir plus à ce sujet ici .

Faites attention à ne pas confondre le code précédent avec ce qui suit:

let [r1, r2] = [await t1(100), await t2(200)];
function t1(t) {
  console.time(`task ${t}`);
  console.log(`start task ${t}`);
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.timeEnd(`task ${t}`);
      resolve();
    }, t);
  })
}
console.log('Promise');
Promise.all([t1(100), t1(200), t1(10)]).then(async() => {

  console.log('Await');
  let [r1, r2, r3] = [await t1(100), await t1(200), await t1(10)]
});

L'utilisation de ces deux méthodes n'est pas équivalente. En savoir plus sur la différence .

En fin de compte, Promise.all Est une approche plus propre qui s'adapte mieux à un nombre arbitraire de tâches.

9
lucascaro

À ce stade, la seule raison d'utiliser Promises est d'appeler plusieurs tâches asynchrones à l'aide de Promise.all() Sinon, vous êtes généralement mieux avec async/wait ou Observables.

2
XaxD

En fait, cela dépend de la version de votre nœud, mais si vous pouvez utiliser async/await alors votre code sera plus lisible et plus facile à maintenir. Lorsque vous définissez une fonction comme 'async', elle retourne un Promise natif, et lorsque vous l'appelez à l'aide de wait, elle exécute Promise.then.

Remarque: placez vos appels d'attente dans un try/catch, car si la promesse échoue, elle émet 'catch' que vous pouvez gérer à l'intérieur du bloc catch.

try{
let res1 = await your-async-function(parameters);
let res2 = await your-promise-function(parameters);
await your-async-or-promise-function(parameters);
}
catch(ex){
// your error handler goes here
// error is caused by any of your called functions which fails its promise
// this methods breaks your call chain
}

vous pouvez également gérer votre "capture" comme ceci:

let result = await your-asyncFunction(parameters).catch((error)=>{//your error handler goes here});

cette méthode mentionnée ne produit pas d'exception donc l'exécution continue.

Je ne pense pas qu'il y ait de différence de performances entre async/await autre que l'implémentation native du module Promise.

Je suggère d'utiliser le module bluebird au lieu de la promesse native intégrée au nœud.

1
mohammad mohammad

Cela dépend de l'approche avec laquelle vous êtes bon, promettre et asynchroniser/attendre sont bons, mais si vous voulez écrire du code asynchrone, en utilisant une structure de code synchrone, vous devez utiliser l'approche asynchrone/attendre.Comme dans l'exemple suivant, une fonction renvoie l'utilisateur avec les deux Promesse ou async/style d'attente. si nous utilisons Promise:

function getFirstUser() {
    return getUsers().then(function(users) {
        return users[0].name;
    }).catch(function(err) {
        return {
          name: 'default user'
        };
    });
}

si nous utilisons aysnc/wait

async function getFirstUser() {
    try {
        let users = await getUsers();
        return users[0].name;
    } catch (err) {
        return {
            name: 'default user'
        };
    }
}

Ici, dans l'approche prometteuse, nous avons besoin d'une structure pouvant être suivie et dans l'approche asynchrone/attend, nous utilisons "attendent" pour maintenir l'exécution de la fonction asynchrone.

vous pouvez vérifier ce lien pour plus de clarté Visitez https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8

0
Sumit Kumar

Hier, j'ai pris la décision provisoire de passer de l'utilisation de Promises à l'utilisation d'Async/Await, indépendamment de nodejs, en raison de la difficulté à accéder aux valeurs précédentes de la chaîne Promise. J'ai trouvé une solution compacte en utilisant 'bind' pour enregistrer les valeurs à l'intérieur des fonctions 'then', mais Async semblait beaucoup plus agréable (et c'était le cas) en permettant un accès direct aux variables et arguments locaux. Et l'avantage le plus évident d'Async/Await est, bien sûr, l'élimination des fonctions explicites distrayantes "alors" au profit d'une notation linéaire qui ressemble beaucoup aux appels de fonctions ordinaires.

Cependant, ma lecture aujourd'hui a révélé des problèmes avec Async/Await, qui déraillent ma décision. Je pense que je vais m'en tenir à Promises (éventuellement en utilisant un préprocesseur de macro pour simplifier les fonctions "alors") jusqu'à ce que Async/Await soit corrigé, dans quelques années.

Voici les problèmes que j'ai trouvés. Je serais ravi de découvrir que je me trompe, que ceux-ci ont des solutions faciles.

  1. Nécessite un try/catch externe ou un Promise.catch () final, sinon les erreurs et les exceptions sont perdues.

  2. Une dernière attente nécessite soit une fonction Promise.then (), soit une fonction asynchrone externe supplémentaire.

  3. L'itération ne peut être effectuée correctement qu'avec for/of, pas avec d'autres itérateurs.

  4. Attendre ne peut attendre qu'une seule promesse à la fois, pas des promesses parallèles comme des chaînes de promesses avec Promise.all.

  5. Await ne prend pas en charge Promise.race (), en cas de besoin.

0
David Spector