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 !
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... }); }); });
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. userLogin
、getararticle
和 showararticle
嵌套了三个promise。这样复杂性将按代码行比例增长,它可能变得不可读。
为了避免这种情况,我们需要解除代码的嵌套,从第一个 then
中返回 getArticle
,然后在第二个 then
中处理它。
userLogin('user') .then(getArticle) .then(showArticle) .then(function(){ //Your code goes here... });
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));
在上面的例子中,我们在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));
注意:在 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('message'); }).catch(e => console.log(e.message)); (async () => { try { await new Promise(async () => { throw new Error('message'); }); } catch (e) { console.log(e.message); } })();
当我在Promise块内遇到 async
函数时,我试图将 async
逻辑保持在 Promise 块之外,以保持其同步性。10次中有9次都能成功。
然而,在某些情况下,可能需要一个 async
函数。在这种情况下,也别无选择,只能用try/catch
块来手动管理。
new Promise(async (resolve, reject) => { try { throw new Error('message'); } 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('message'); } catch (error) { reject(error); } }); } catch (e) { console.log(e.message); } })();
4.在创建 Promise 后立即执行 Promise 块
至于下面的代码片断,如果我们把代码片断放在调用HTTP请求的地方,它就会被立即执行。
const myPromise = new Promise(resolve => { // code to make HTTP request resolve(result); });
原因是这段代码被包裹在一个Promise构造函数中。然而,有些人可能会认为只有在执行myPromise
的then
方法之后才被触发。
然而,真相并非如此。相反,当一个Promise被创建时,回调被立即执行。
这意味着在建立 myPromise
之后到达下面一行时,HTTP请求很可能已经在运行,或者至少处于调度状态。
Promises 总是急于执行过程。
但是,如果希望以后再执行 Promises,应该怎么做?如果现在不想发出HTTP请求怎么办?是否有什么神奇的机制内置于 Promises 中,使我们能够做到这一点?
答案就是使用函数。函数是一种耗时的机制。只有当开发者明确地用 ()
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); });
🎜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('util'); 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('sequential'); await f1(); await f2(); await f3(); console.timeEnd('sequential'); })();
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('concurrent'); await Promise.all([f1(), f2(), f3()]); console.timeEnd('concurrent'); })();
.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); });
对于HTTP请求,Promise 构造函数和回调函数只有在函数被执行时才会被调用。所以现在我们有一个懒惰的Promise,只有在我们需要的时候才会执行。
5. 不一定使用 Promise.all() 方法
如果你已经工作多年,应该已经知道我在说什么了。如果有许多彼此不相关的 Promise,我们可以同时处理它们。
Promise 是并发的,但如你一个一个地等待它们,会太费时间,Promise.all()
可以节省很多时间。
记住,Promise.all() 是我们的朋友
const { promisify } = require('util'); 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('sequential'); await f1(); await f2(); await f3(); console.timeEnd('sequential'); })();
上述代码的执行时间约为 6
秒。但如果我们用 Promise.all()
代替它,将减少执行时间。
(async () => { console.time('concurrent'); await Promise.all([f1(), f2(), f3()]); console.timeEnd('concurrent'); })();
总结
在这篇文章中,我们讨论了使用 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!