[解決済み] プロミスは単なるコールバックではないのか?
質問
数年前からJavaScriptを開発していますが、プロミスについての騒動が全く理解できません。
変更ばかりしているような気がします。
api(function(result){
api2(function(result2){
api3(function(result3){
// do work
});
});
});
のようなライブラリを使用することができます。 非同期 のようなもので、とにかく
api().then(function(result){
api2().then(function(result2){
api3().then(function(result3){
// do work
});
});
});
どちらがコード量が多く、可読性に劣るでしょうか。ここでは何も得られなかったし、突然魔法のように「フラット」になったわけでもない。もちろん、プロミスに変換しなければならないのは言うまでもありません。
では、ここでプロミスについて大騒ぎしているのは何なのか?
どのように解決するのか?
プロミスはコールバックではありません。プロミスは 非同期操作の将来の結果 . もちろん、そのような書き方をしていても、ほとんどメリットはありません。しかし、本来の使い方をすれば、非同期コードを同期コードに似た形で書くことができ、より簡単に従うことができます。
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
});
確かに、コードはあまり減りませんが、読みやすさは格段に向上しています。
しかし、これで終わりではありません。本当の効果を発見してみましょう。もし、ステップのどれかにエラーがないかチェックしたいとしたらどうでしょう?コールバックでそれを行うのは大変ですが、プロミスを使えば楽勝です。
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
}).catch(function(error) {
//handle any error that may occur before this point
});
とほぼ同じです。
try { ... } catch
ブロックを作成します。
もっといいのは
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
}).catch(function(error) {
//handle any error that may occur before this point
}).then(function() {
//do something whether there was an error or not
//like hiding an spinner if you were performing an AJAX request.
});
そして、さらに良いことがあります。もし、これらの3つの呼び出しを
api
,
api2
,
api3
は同時に実行できましたが (たとえば AJAX 呼び出しの場合)、3 つの待ち時間が必要だったのでしょうか。プロミスがなければ、ある種のカウンターを作らなければならないはずです。約束があれば、ES6記法を使用して、別のケーキの部分とかなりきれいです。
Promise.all([api(), api2(), api3()]).then(function(result) {
//do work. result is an array contains the values of the three fulfilled promises.
}).catch(function(error) {
//handle the error. At least one of the promises rejected.
});
プロミスを新しい視点で見ていただけると幸いです。
関連
-
JavaScriptにおけるマクロタスクとミクロタスクの詳細
-
jQueryのコピーオブジェクトの説明
-
[解決済み】React-Redux: アクションはプレーンオブジェクトでなければならない。非同期アクションにはカスタムミドルウェアを使用する
-
[解決済み】「.addEventListener is not a function」なぜこのエラーが発生するのか?
-
[解決済み] jQueryのディファレンシャルとプロミス - .then() vs .done()
-
[解決済み] 既存のコールバックAPIをプロミスに変換するにはどうすればよいですか?
-
[解決済み] 約束事を次々と解決していく(=順番に解決していく)?
-
[解決済み】PromiseとObservablesの違いは何ですか?
-
[解決済み】一部の約束が拒否されても、すべての約束が完了するまで待つ
-
[解決済み】JavaScriptのプロミス - reject vs. throw
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
親子コンポーネント通信を解決する3つのVueスロット
-
fetch ネットワークリクエストラッパーの説明例
-
Vueの要素ツリーコントロールに破線を追加する説明
-
vue3.0プロジェクトのアーキテクチャを構築するための便利なツール
-
vue for 登録ページ効果 vue for sms 認証コードログイン
-
Vueにシンプルなメモ帳機能を実装
-
VUEグローバルフィルターの概念と留意点、基本的な使い方
-
[解決済み】ERROR エラーです。スイッチのname属性が指定されていないフォームコントロールの値アクセッサがない
-
[解決済み】(Google Map API) Geocodeは以下の理由で成功しませんでした。REQUEST_DENIED
-
フロントエンド null のプロパティ 'disabled' を読み取れない 問題が解決された