Maison > interface Web > js tutoriel > le corps du texte

Évitez rapidement les pièges et parlez de 5 erreurs courantes dans l'utilisation des promesses !

青灯夜游
Libérer: 2021-12-08 10:22:19
avant
1873 Les gens l'ont consulté

Cet article partagera avec vous 5 erreurs courantes lors de l'utilisation des promesses pour vous aider à éviter rapidement les pièges. J'espère qu'il sera utile à tout le monde !

Évitez rapidement les pièges et parlez de 5 erreurs courantes dans l'utilisation des promesses !

Promise fournit un moyen élégant de gérer les opérations asynchrones en JS. C’est aussi une solution pour éviter « l’enfer des rappels ». Cependant, peu de développeurs comprennent ce que cela implique. C’est pourquoi de nombreuses personnes ont tendance à commettre des erreurs dans la pratique. [Recommandations associées : Tutoriel d'apprentissage javascript]

Dans cet article, nous présentons cinq erreurs courantes lors de l'utilisation des promesses, et espérons que tout le monde pourra éviter ces erreurs.

1. Évitez l'enfer des promesses

Habituellement, Promise est utilisé pour éviter l'enfer des rappels. Mais en abuser peut aussi conduire à ce que Promises soit un enfer.

userLogin('user').then(function(user){
    getArticle(user).then(function(articles){
        showArticle(articles).then(function(){
            //Your code goes here...
        });
    });
});
Copier après la connexion

Dans l'exemple ci-dessus, nous avons trois promesses imbriquées pour userLogin, getararticle et showararticle. De cette façon, la complexité augmentera proportionnellement aux lignes de code et risque de devenir illisible. userLogingetararticleshowararticle 嵌套了三个promise。这样复杂性将按代码行比例增长,它可能变得不可读。

为了避免这种情况,我们需要解除代码的嵌套,从第一个 then 中返回 getArticle,然后在第二个 then 中处理它。

userLogin('user')
  .then(getArticle)
  .then(showArticle)
  .then(function(){
       //Your code goes here...
});
Copier après la connexion

2. 在 Promise 中使用 <span style="font-size: 18px;">try/catch</span>

通常情况下,我们使用 try/catch 块来处理错误。然而,不建议在 Promise 对象中使用try/catch

这是因为如果有任何错误,Promise对象会在 catch 内自动处理。

ew Promise((resolve, reject) => {
  try {
    const data = doThis();
    // do something
    resolve();
  } catch (e) {
    reject(e);
  }
})
  .then(data => console.log(data))
  .catch(error => console.log(error));
Copier après la connexion

在上面的例子中,我们在Promise 内使用了 try/catch 块。

但是,Promise本身会在其作用域内捕捉所有的错误(甚至是打字错误),而不需要 try/catch块。它确保在执行过程中抛出的所有异常都被获取并转换为被拒绝的 Promise。

new Promise((resolve, reject) => {
  const data = doThis();
  // do something
  resolve()
})
  .then(data => console.log(data))
  .catch(error => console.log(error));
Copier après la connexion

注意:在 Promise 块中使用 .catch() 块是至关重要的。否则,你的测试案例可能会失败,而且应用程序在生产阶段可能会崩溃。

3. 在 Promise 块内使用异步函数

Async/Await 是一种更高级的语法,用于处理同步代码中的多个Promise。当我们在一个函数声明前使用 async 关键字时,它会返回一个 Promise,我们可以使用 await 关键字来停止代码,直到我们正在等待的Promise解决或拒绝。

但是,当你把一个 Async 函数放在一个 Promise 块里面时,会有一些副作用。

假设我们想在Promise 块中做一个异步操作,所以使用了 async 关键字,但,不巧的是我们的代码抛出了一个错误。

这样,即使使用 catch() 块或在 try/catch 块内等待你的Promise,我们也不能立即处理这个错误。请看下面的例子。

// 此代码无法处理错误
new Promise(async () => {
  throw new Error(&#39;message&#39;);
}).catch(e => console.log(e.message));

(async () => {
  try {
    await new Promise(async () => {
      throw new Error(&#39;message&#39;);
    });
  } catch (e) {
    console.log(e.message);
  }
})();
Copier après la connexion

当我在Promise块内遇到 async 函数时,我试图将 async 逻辑保持在 Promise 块之外,以保持其同步性。10次中有9次都能成功。

然而,在某些情况下,可能需要一个 async 函数。在这种情况下,也别无选择,只能用try/catch 块来手动管理。

new Promise(async (resolve, reject) => {
  try {
    throw new Error(&#39;message&#39;);
  } catch (error) {
    reject(error);
  }
}).catch(e => console.log(e.message));


//using async/await
(async () => {
  try {
    await new Promise(async (resolve, reject) => {
      try {
        throw new Error(&#39;message&#39;);
      } catch (error) {
        reject(error);
      }
    });
  } catch (e) {
    console.log(e.message);
  }
})();
Copier après la connexion

4.在创建 Promise 后立即执行 Promise 块

至于下面的代码片断,如果我们把代码片断放在调用HTTP请求的地方,它就会被立即执行。

const myPromise = new Promise(resolve => {
  // code to make HTTP request
  resolve(result);
});
Copier après la connexion

原因是这段代码被包裹在一个Promise构造函数中。然而,有些人可能会认为只有在执行myPromisethen方法之后才被触发。

然而,真相并非如此。相反,当一个Promise被创建时,回调被立即执行。

这意味着在建立 myPromise 之后到达下面一行时,HTTP请求很可能已经在运行,或者至少处于调度状态。

Promises 总是急于执行过程。

但是,如果希望以后再执行 Promises,应该怎么做?如果现在不想发出HTTP请求怎么办?是否有什么神奇的机制内置于 Promises 中,使我们能够做到这一点?

答案就是使用函数。函数是一种耗时的机制。只有当开发者明确地用 ()

Pour éviter cette situation, nous devons désimbriquer le code, renvoyer getArticle du premier puis, puis le renvoyer dans le second puis code> pour le gérer. 🎜
const createMyPromise = () => new Promise(resolve => {
  // HTTP request
  resolve(result);
});
Copier après la connexion
Copier après la connexion
🎜🎜🎜2. Utilisez le bloc 🎜🎜try/catch🎜🎜 dans Promise🎜🎜🎜🎜Normalement, nous utilisons le bloc try/catch pour gérer les erreurs. Cependant, il n'est pas recommandé d'utiliser try/catch dans un objet Promise. 🎜🎜En effet, s'il y a des erreurs, l'objet Promise sera automatiquement traité dans catch. 🎜
const { promisify } = require(&#39;util&#39;);
const sleep = promisify(setTimeout);

async function f1() {
  await sleep(1000);
}

async function f2() {
  await sleep(2000);
}

async function f3() {
  await sleep(3000);
}


(async () => {
  console.time(&#39;sequential&#39;);
  await f1();
  await f2();
  await f3();
  console.timeEnd(&#39;sequential&#39;);  
})();
Copier après la connexion
Copier après la connexion
🎜Dans l'exemple ci-dessus, nous avons utilisé le bloc try/catch à l'intérieur de la promesse. 🎜🎜Cependant, Promise lui-même détectera toutes les erreurs (même les fautes de frappe) dans son champ d'application sans avoir besoin d'un bloc try/catch. Il garantit que toutes les exceptions levées lors de l'exécution sont interceptées et converties en promesses rejetées. 🎜
(async () => {
    console.time(&#39;concurrent&#39;);
    await Promise.all([f1(), f2(), f3()]);
    console.timeEnd(&#39;concurrent&#39;); 
  })();
Copier après la connexion
Copier après la connexion
🎜🎜Remarque : 🎜Il est crucial d'utiliser les blocs .catch() dans les blocs Promise. Sinon, vos cas de test risquent d'échouer et l'application risque de planter pendant la phase de production. 🎜🎜🎜🎜3. Utilisez des fonctions asynchrones dans les blocs Promise 🎜🎜🎜🎜Async/Await est une syntaxe plus avancée pour gérer plusieurs promesses dans du code synchrone. Lorsque nous utilisons le mot-clé async avant une déclaration de fonction, il renverra une promesse. Nous pouvons utiliser le mot-clé await pour arrêter le code jusqu'à ce que la promesse que nous attendons soit résolue. ou refuser. 🎜🎜🎜Cependant, lorsque vous placez une fonction Async dans un bloc Promise, il y aura des effets secondaires. 🎜🎜🎜Supposons que nous voulions effectuer une opération asynchrone dans le bloc Promise, nous utilisons donc le mot-clé async, mais malheureusement notre code génère une erreur. 🎜🎜De cette façon, même si vous utilisez un bloc catch() ou attendez votre promesse dans un bloc try/catch, nous ne pouvons pas gérer l'erreur immédiatement. Veuillez consulter l'exemple ci-dessous. 🎜rrreee🎜Lorsque je rencontre une fonction async à l'intérieur d'un bloc Promise, j'essaie de garder la logique async en dehors du bloc Promise pour la garder synchronisée. Cela fonctionne 9 fois sur 10. 🎜🎜Cependant, dans certains cas, une fonction async peut être requise. Dans ce cas, il n'y a pas d'autre choix que de le gérer manuellement à l'aide des blocs try/catch. 🎜rrreee🎜🎜🎜4. Exécutez le bloc Promise immédiatement après avoir créé la Promise🎜🎜🎜🎜Quant à l'extrait de code ci-dessous, si nous plaçons l'extrait de code là où la requête HTTP est appelée, il sera exécuté immédiatement. 🎜rrreee🎜La raison est que ce code est enveloppé dans un constructeur Promise. Cependant, certaines personnes peuvent penser qu'il n'est déclenché qu'après l'exécution de la méthode then de myPromise. 🎜🎜🎜Cependant, la vérité n'est pas vraie. En revanche, lorsqu'une promesse est créée, le rappel est exécuté immédiatement. 🎜🎜🎜Cela signifie qu'au moment où la ligne suivante est atteinte après l'établissement de myPromise, la requête HTTP est très probablement déjà en cours d'exécution, ou du moins dans un état planifié. 🎜🎜🎜Les promesses sont toujours désireuses d'exécuter le processus. 🎜🎜🎜Mais que devez-vous faire si vous souhaitez exécuter les promesses à l'avenir ? Que faire si je ne souhaite pas faire de requête HTTP maintenant ? Existe-t-il un mécanisme magique intégré à Promises qui nous permet de faire cela ? 🎜🎜La réponse est d'utiliser des fonctions. Les fonctions sont un mécanisme qui prend du temps. Ils ne seront exécutés que si le développeur les appelle explicitement avec (). La simple définition d’une fonction ne nous mène nulle part. Ainsi, le moyen le plus efficace de rendre une promesse paresseuse est de l'envelopper dans une fonction 🎜 !
const createMyPromise = () => new Promise(resolve => {
  // HTTP request
  resolve(result);
});
Copier après la connexion
Copier après la connexion

对于HTTP请求,Promise 构造函数和回调函数只有在函数被执行时才会被调用。所以现在我们有一个懒惰的Promise,只有在我们需要的时候才会执行。

5. 不一定使用 Promise.all() 方法

如果你已经工作多年,应该已经知道我在说什么了。如果有许多彼此不相关的 Promise,我们可以同时处理它们。

Promise 是并发的,但如你一个一个地等待它们,会太费时间,Promise.all()可以节省很多时间。

记住,Promise.all() 是我们的朋友
const { promisify } = require(&#39;util&#39;);
const sleep = promisify(setTimeout);

async function f1() {
  await sleep(1000);
}

async function f2() {
  await sleep(2000);
}

async function f3() {
  await sleep(3000);
}


(async () => {
  console.time(&#39;sequential&#39;);
  await f1();
  await f2();
  await f3();
  console.timeEnd(&#39;sequential&#39;);  
})();
Copier après la connexion
Copier après la connexion

上述代码的执行时间约为 6 秒。但如果我们用 Promise.all() 代替它,将减少执行时间。

(async () => {
    console.time(&#39;concurrent&#39;);
    await Promise.all([f1(), f2(), f3()]);
    console.timeEnd(&#39;concurrent&#39;); 
  })();
Copier après la connexion
Copier après la connexion

总结

在这篇文章中,我们讨论了使用 Promise 时常犯的五个错误。然而,可能还有很多简单的问题需要仔细解决。

如果你还有更多相关的错误,欢迎留言一起讨论。

英文原文地址:https://blog.bitsrc.io/5-common-mistakes-in-using-promises-bfcc4d62657f

作者:Ravidu Perera

更多编程相关知识,请访问:编程入门!!

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!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal