この記事では、落とし穴をすぐに回避できるように、Promise を使用するときによくある 5 つの間違いを紹介します。
#Promise は、JS で非同期操作を処理するエレガントな方法を提供します。これは「コールバック地獄」を回避するための解決策でもあります。ただし、その内容を理解している開発者はそれほど多くありません。そのため、練習ではミスをしてしまう人が多いです。 [関連する推奨事項: JavaScript 学習チュートリアル #]
この記事では、Promise を使用する際によくある 5 つの間違いを紹介し、誰もがこれらの間違いを回避できることを願っています。
1. Promise 地獄の回避#
##通常、Promise はコールバック 地獄を回避するために使用されます。しかし、それらを乱用すると、プロミスが地獄になる可能性もあります。userLogin('user').then(function(user){ getArticle(user).then(function(articles){ showArticle(articles).then(function(){ //Your code goes here... }); }); });
userLogin、
getararticle、
showararticle の 3 つのネストされた Promise があります。このようにすると、コードの行数に比例して複雑さが増し、読めなくなる可能性があります。
then から
getArticle を返し、次に 2 番目の
then で処理する必要があります。それ。
userLogin('user') .then(getArticle) .then(showArticle) .then(function(){ //Your code goes here... });
2. Promise # で try/catch<span style="font-size: 18px;"></span>
block を使用します##通常、エラーを処理するには
ブロックを使用します。ただし、Promise
オブジェクト内で try/catch
を使用することはお勧めできません。 これは、エラーが発生した場合、Promise オブジェクトが
内で自動的に処理されるためです。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">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));</pre><div class="contentsignin">ログイン後にコピー</div></div>
上の例では、Promise 内で
ブロックを使用しました。 ただし、Promise 自体は、
ブロックを必要とせずに、スコープ内のすべてのエラー (タイプミスも含む) をキャッチします。これにより、実行中にスローされたすべての例外が確実にキャッチされ、拒否された Promise に変換されます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">new Promise((resolve, reject) => {
const data = doThis();
// do something
resolve()
})
.then(data => console.log(data))
.catch(error => console.log(error));</pre><div class="contentsignin">ログイン後にコピー</div></div>
Promise ブロック内で .catch() ブロックを使用することが重要です。そうしないと、テスト ケースが失敗し、本番フェーズ中にアプリケーションがクラッシュする可能性があります。
3. Promise ブロック内で非同期関数を使用する
Async/Await はより高度な構文であり、処理に使用されます。同期コード内の複数の Promise。関数宣言の前に async
キーワードを使用すると、Promise が返されます。await
キーワードを使用すると、待機している Promise が解決または拒否されるまでコードを停止できます。 . .
Promise ブロックで非同期操作を実行したいので、
async キーワードを使用しますが、残念ながらコードがエラーをスローするとします。 このように、
ブロックを使用したり、try/catch
ブロック内で Promise を待機したりしても、エラーをすぐに処理することはできません。以下の例を参照してください。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">// 此代码无法处理错误
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);
}
})();</pre><div class="contentsignin">ログイン後にコピー</div></div>
Promise ブロック内で
関数に遭遇した場合、同期を保つために async
ロジックを Promise ブロックの外に保持しようとします。 10回中9回は機能します。 ただし、場合によっては、
関数が必要になる場合があります。この場合は、try/catch
ブロックを使用して手動で管理するしかありません。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">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);
}
})();</pre><div class="contentsignin">ログイン後にコピー</div></div>
4. Promise を作成した直後に Promise ブロックを実行します次のコード スニペットのように、コード スニペットをHTTP 呼び出しが要求されると、すぐに実行されます。
const myPromise = new Promise(resolve => { // code to make HTTP request resolve(result); });
その理由は、このコードが Promise コンストラクターでラップされているためです。ただし、
myPromise の then
メソッドが実行された後にのみトリガーされると考える人もいるかもしれません。
これは、
myPromise の確立後に次の行に到達するまでに、HTTP リクエストがすでに実行されているか、少なくともスケジュールされた状態になっている可能性が高いことを意味します。
しかし、将来約束を実行したい場合はどうすればよいでしょうか?今すぐ HTTP リクエストを実行したくない場合はどうすればよいですか?これを可能にする魔法のメカニズムが Promise に組み込まれているのでしょうか?
答えは関数を使用することです。関数は時間のかかるメカニズムです。これらは、開発者が
() を使用して明示的に呼び出した場合にのみ実行されます。関数を定義するだけでは何も進みません。したがって、Promise を遅延させる最も効率的な方法は、Promise を関数でラップすることです!<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">const createMyPromise = () => new Promise(resolve => {
// HTTP request
resolve(result);
});</pre><div class="contentsignin">ログイン後にコピー</div></div><p>对于HTTP请求,Promise 构造函数和回调函数只有在函数被执行时才会被调用。所以现在我们有一个懒惰的Promise,只有在我们需要的时候才会执行。</p><p><strong><span style="font-size: 18px;">5. 不一定使用 Promise.all() 方法</span></strong></p><p>如果你已经工作多年,应该已经知道我在说什么了。如果有许多彼此不相关的 Promise,我们可以同时处理它们。</p><p>Promise 是并发的,但如你一个一个地等待它们,会太费时间,<code>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
更多编程相关知识,请访问:编程入门!!
以上が落とし穴をすぐに避け、Promise を使用する際によくある 5 つの間違いについて説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。