Es6-promises

提供:Dev Guides
移動先:案内検索

ES6-約束

約束の構文

*p* はpromiseオブジェクト、 *resolve* はpromiseが正常に実行されたときに呼び出す必要がある関数、 *reject* はpromiseがエラーに遭遇したときに呼び出す必要がある関数です。 。
let p = new Promise(function(resolve,reject){
   let workDone = true;//some time consuming work
      if(workDone){
     //invoke resolve function passed

      resolve('success promise completed')
   }
   else{
      reject('ERROR , work could not be completed')
   }
})

以下の例は、2つの数値を非同期的に加算する関数* add_positivenos_async()*を示しています。 正の値が渡されると、約束は解決されます。 負の値が渡されると、約束は拒否されます。

<script>
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
           //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
         })
         return p;
   }

   add_positivenos_async(10, 20)
      .then(successHandler)//if promise resolved
      .catch(errorHandler);//if promise rejected

   add_positivenos_async(-10, -20)
      .then(successHandler)//if promise resolved
      .catch(errorHandler);//if promise rejected

   function errorHandler(err) {
      console.log('Handling error', err)
   }
   function successHandler(result) {
      console.log('Handling success', result)
   }

   console.log('end')
</script>

上記のコードの出力は以下のようになります-

end
Handling success 30
Handling error NOT_Postive_Number_Passed

約束の連鎖

  • Promiseチェーニング*は、一連の*非同期タスク*を次々に実行するときに使用できます。 約束が別の約束の結果に依存する場合、約束は連鎖します。 これは以下の例に示されています

以下の例では、* add_positivenos_async()関数*は2つの数値を非同期的に加算し、負の値が渡された場合は拒否します。 現在の非同期関数呼び出しの結果は、後続の関数呼び出しにパラメーターとして渡されます。 各* then()*メソッドにはreturnステートメントがあることに注意してください。

<script>
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
           //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })
      return p;
   }

   add_positivenos_async(10,20)
   .then(function(result){
      console.log("first result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
   console.log("second result",result)
      return add_positivenos_async(result,result)
   }).then(function(result){
      console.log("third result",result)
   })

   console.log('end')
</script>

上記のコードの出力は以下のようになります-

end
first result 30
second result 60
third result 120

promiseオブジェクトのいくつかの一般的に使用されるメソッドについて、以下で詳しく説明します-

promise.all()

このメソッドは、複数のpromiseの結果を集約するのに役立ちます。

構文

  • promise.all()メソッドの構文を以下に示します。ここで、 *iterable は反復可能なオブジェクトです。 E.g. アレイ。
Promise.all(iterable);

以下の例では、非同期操作の配列を実行します [add_positivenos_async(10,20)、add_positivenos_async(30,40)、add_positivenos_async(50,60)] 。 すべての操作が完了すると、約束は完全に解決されます。

<script>
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
           //do some complex time consuming work
            resolve(n1 + n2)
         }
         else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }
  //Promise.all(iterable)

Promise.all([add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)])
   .then(function(resolveValue){
      console.log(resolveValue[0])
      console.log(resolveValue[1])
      console.log(resolveValue[2])
      console.log('all add operations done')
   })
   .catch(function(err){
      console.log('Error',err)
   })
   console.log('end')
</script>

上記のコードの出力は次のようになります-

end
30
70
110
all add operations done

promise.race()

この関数は、約束の配列を取り、解決された最初の約束を返します。

構文

  • promise.race()*関数の構文を以下に示します。ここで、iterableは反復可能なオブジェクトです。 E.g. アレイ。
Promise.race(iterable)

以下の例では、非同期操作の配列 [add_positivenos_async(10,20)、add_positivenos_async(30,40)] を使用しています。

追加操作のいずれかが完了するたびに、promiseが解決されます。 promiseは、他の非同期操作が完了するのを待ちません。

<script>
   function add_positivenos_async(n1, n2) {
      let p = new Promise(function (resolve, reject) {
         if (n1 >= 0 && n2 >= 0) {
           //do some complex time consuming work
            resolve(n1 + n2)
         } else
            reject('NOT_Postive_Number_Passed')
      })

      return p;
   }

  //Promise.race(iterable)
   Promise.race([add_positivenos_async(10,20),add_positivenos_async(30,40)])
   .then(function(resolveValue){
      console.log('one of them is done')
      console.log(resolveValue)
   }).catch(function(err){
      console.log("Error",err)
   })

   console.log('end')
</script>

上記のコードの出力は次のようになります-

end
one of them is done
30
*Promises* は、JavaScriptで非同期プログラミングを実装するためのクリーンな方法です(ES6新機能)。 約束の前に、コールバックは非同期プログラミングを実装するために使用されました。 コールバックを使用して、非同期プログラミングとその実装を理解することから始めましょう。

コールバックについて

関数は、パラメーターとして別の関数に渡すことができます。 このメカニズムは*コールバック*と呼ばれます。 コールバックはイベントで役立ちます。

次の例は、この概念をよりよく理解するのに役立ちます。

<script>
   function notifyAll(fnSms, fnEmail) {
      console.log('starting notification process');
      fnSms();
      fnEmail();
   }
   notifyAll(function() {
      console.log("Sms send ..");
   },
   function() {
      console.log("email send ..");
   });
   console.log("End of script");
  //executes last or blocked by other methods
</script>

上記の* notifyAll()*メソッドでは、SMSの送信と電子メールの送信によって通知が行われます。 したがって、notifyAllメソッドの呼び出し側は、2つの関数をパラメーターとして渡す必要があります。 各機能は、SMSの送信や電子メールの送信などの単一の責任を負います。

上記のコードが正常に実行されると、次の出力が表示されます。

starting notification process
Sms send ..
Email send ..
End of script

上記のコードでは、関数呼び出しは同期的です。 これは、UIスレッドが通知プロセス全体を完了するのを待っていることを意味します。 同期コールはブロッキングコールになります。 ノンブロッキングまたは非同期呼び出しを理解しましょう。

AsyncCallbackを理解する

上記の例を考えてみましょう。

スクリプトを有効にするには、notifyAll()メソッドの非同期呼び出しまたは非ブロッキング呼び出しを実行します。 JavaScriptの* setTimeout()*メソッドを使用します。 このメソッドはデフォルトで非同期です。

setTimeout()メソッドは2つのパラメータを取ります-

  • コールバック関数。
  • メソッドが呼び出されるまでの秒数。

この場合、通知プロセスはタイムアウトでラップされています。 したがって、コードで設定された2秒の遅延がかかります。 notifyAll()が呼び出され、メインスレッドは他のメソッドを実行するように進みます。 したがって、通知プロセスはメインのJavaScriptスレッドをブロックしません。

<script>
   function notifyAll(fnSms, fnEmail) {
      setTimeout(function() {
         console.log('starting notification process');
         fnSms();
         fnEmail();
      }, 2000);
   }
   notifyAll(function() {
      console.log("Sms send ..");
   },
   function() {
      console.log("email send ..");
   });
   console.log("End of script");//executes first or not blocked by others
</script>

上記のコードが正常に実行されると、次の出力が表示されます。

End of script
starting notification process
Sms send ..
Email send ..

複数のコールバックの場合、コードは恐ろしく見えます。

<script>
   setTimeout(function() {
      console.log("one");
      setTimeout(function() {
         console.log("two");
         setTimeout(function() {
            console.log("three");
         }, 1000);
      }, 1000);
   }, 1000);
</script>

ES6は、Promiseの概念を導入することにより、あなたを助けます。 プロミスは「継続イベント」であり、複数の非同期操作をよりクリーンなコードスタイルで一緒に実行するのに役立ちます。

例でこれを理解しましょう。 以下は同じ構文です。

var promise = new Promise(function(resolve , reject) {
  //do a thing, possibly async , then..
   if(/*everthing turned out fine */)    resolve("stuff worked");
   else
   reject(Error("It broke"));
});
return promise;
//Give this to someone

promiseを実装するための最初のステップは、promiseを使用するメソッドを作成することです。 この例では、* getSum()*メソッドは非同期です。つまり、その操作は他のメソッドの実行をブロックしてはいけません。 この操作が完了するとすぐに、呼び出し元に通知します。

次の例(ステップ1)は、Promiseオブジェクト「var promise」を宣言しています。 Promise Constructorは、作業が正常に完了するために最初に機能を使用し、エラーが発生した場合に別の機能を使用します。

promiseは、resolveコールバックを使用して結果を渡すことにより、計算の結果、つまりn1 + n2を返します。

  • ステップ1 *-resolve(n1 + n2);

getSum()でエラーまたは予期しない状態が発生した場合、Promiseでリジェクトコールバックメソッドを呼び出し、エラー情報を呼び出し元に渡します。

  • ステップ2 *-reject(Error( "Negatives not supported"));

メソッドの実装は、次のコードに記載されています(ステップ1)。

function getSum(n1, n2) {
   varisAnyNegative = function() {
      return n1 < 0 || n2 < 0;
   }
   var promise = new Promise(function(resolve, reject) {
      if (isAnyNegative()) {
         reject(Error("Negatives not supported"));
      }
      resolve(n1 + n2)
   });
   return promise;
}

2番目のステップでは、呼び出し元の実装について詳しく説明します(ステップ2)。

呼び出し元は「then」メソッドを使用する必要があります。このメソッドは、成功と失敗の2つのコールバックメソッドを取ります。 次のコードに示すように、各メソッドは1つのパラメーターを取ります。

getSum(5, 6)
.then(function (result) {
   console.log(result);
},
function (error) {
   console.log(error);
});

上記のコードが正常に実行されると、次の出力が表示されます。

11

getSum()の戻り値の型はPromiseであるため、実際には複数の「then」ステートメントを使用できます。 最初の「then」にはreturnステートメントがあります。

getSum(5, 6)
.then(function(result) {
   console.log(result);
   returngetSum(10, 20);
  //this returns another promise
},
function(error) {
   console.log(error);
})
.then(function(result) {
   console.log(result);
},
function(error) {
   console.log(error);
});

上記のコードが正常に実行されると、次の出力が表示されます。

11
30

次の例では、getSum()メソッドを使用して3つのthen()呼び出しを発行します。

<script>
   function getSum(n1, n2) {
      varisAnyNegative = function() {
         return n1 < 0 || n2 < 0;
      }
      var promise = new Promise(function(resolve, reject) {
         if (isAnyNegative()) {
            reject(Error("Negatives not supported"));
         }
         resolve(n1 + n2);
      });
      return promise;
   }
   getSum(5, 6)
   .then(function(result) {
      console.log(result);
      returngetSum(10, 20);
     //this returns another Promise
   },
   function(error) {
      console.log(error);
   })
   .then(function(result) {
      console.log(result);
      returngetSum(30, 40);
     //this returns another Promise
   },
   function(error) {
      console.log(error);
   })
   .then(function(result) {
      console.log(result);
   },
   function(error) {
      console.log(error);
   });
   console.log("End of script ");
</script>

上記のコードが正常に実行されると、次の出力が表示されます。

プログラムは最初に「スクリプトの終わり」を表示し、次にgetSum()メソッドを呼び出して結果を1つずつ表示します。

End of script
11
30
70

これは、getSum()が非同期スタイルまたは非ブロックスタイルで呼び出されることを示しています。 Promiseは、コールバックに対処するためのすてきできれいな方法を提供します。