Asyncシリーズ:約束


非同期簡素化、私は約束


コールバックは、我々のasync呼び出しを注文することに役立つことができます.しかし、あまりにも多くの場合は物事が乱雑になる.幸運にも、決定的に示す選択肢があります.いくつかの約束.

地獄の門


このシリーズの最後のポストでは、ネストされたコールバックを使用して次のソリューションに到達しました.
//replace reference to doPrintGreenRed with an anonymous function
printBlue("Blue", function(){
   //calls printGreen with our desired parameter 
   printGreen("Green", function(){
     //calls print red with our desired parameter
     printRed("Red");
   });
});
しかし、より多くのコールバックを必要とするより多くの呼び出しは、我々が定義する必要があります.いくつかの時点でコールバック地獄と呼ばれる現象を体験します.

それがどれくらい汚いかについて言及するために、それは各々のコールバックでexception handlingを実行するでしょう.
try{
 printBlue("Blue", function(){
   try{
     printGreen("Green", function(){
       try{
         printRed("Red");
       }catch(e){
         console.error(e);
       }
     });
   }catch(e){
     console.error(e);
   }
 });
}catch(e){
   console.error(e);
}

それでは何?


2015年にリリースされたJavaScriptの第6版では、約束がリリースされました.コールバックを直接受け入れる代わりに、async関数を使用すると、Promiseオブジェクトを返すことができます.
これらの約束オブジェクトは、async関数の主な作業が完了したときにコールバックを行い、それを実行するthn ()メソッドを提供します.
幸運にも、私たちの印刷機能リターンは約束します、それで、我々の入れ子になったコールバックはとして書き直されることができます.
 printBlue("Blue")//moved our callback from here
  .then(function(){//to here
    printGreen("Green")
     .then(function(){
       printRed("Red");
     })  
  })
目的の出力を得た.しかし、これは本当にコールバックアプローチの改善ですか?それは、まだ非常に類似しているように見えます.この例では、もう一つの約束を返します.
前のものが解決されたと言われたあと、th ()は別の約束を返します.
Then ()を繰り返し呼び出すことで、約束連鎖と呼ばれるものを作ることができます.
 printBlue("Blue")
  .then(function(){
    //only executes after printBlue() resolves
    printGreen("Green");// instead of calling then here
  })
  .then(function(){ // we call it here
    printRed("Red");//only executes after printGreen resolves
  })
  .catch(e){
    console.error(e);
  }  
さて、ネスト化は平坦化されましたが、ここでの主な利点は、Projectオブジェクトによって提供されるcatch ()メソッドの使用です.
チェーンの端のキャッチはチェーンのどんな部分でもスローされたかもしれないどんなエラーも扱うでしょう!
これは読みやすさとエラー処理に関して大きな改善です.

約束をする


どのようにHIGER ADD ADD ()を書くことができるかのように、約束を返す関数のバージョンも書くことができます.print/green/blue関数と異なり、add ()で返されたプロミスは値で解決されます.この値は、th ()メソッドに渡す関数によって受け取られます.
function add(a, b){
  //create a promise object
  const promise = new Promise(function(resolve, reject){
    if(typeof a !== "number" or typeof b !== "number")
      reject("Invalid parameter error");//how errors are thrown
    else
      resolve(a + b);//how values are returned when the work of the function is complete
   })
  return promise;//return our promise
}
ときに2コールバックを供給する必要があります約束オブジェクトを作成するresolve ()とreject ()
値を返すためにreturnを使う代わりに、resolve ()関数を使用します.resolve ()に渡されたものは、this ()のコールバックに渡されます.
スローをスローする代わりにreject ()関数を使用します.reject ()に渡されることはcatch ()のコールバックに渡されます.
add(5,10)
  .then(function(ans){
    console.log(ans);//logs 15
    return ans;//passes this value to next then in the chain
  })
  .then(function(ans){
    return add(ans, 5);//returns a new promise to the next then
  })
  .then(function(ans){
    console.log(finalAns);//logs 20
  });

add(11, 'cat')
  .then(function(ans){
    console.log(ans);
    //this is not executed because of the type check in the add()
  })
  .catch(function(error){
   console.error(error);//logs 'Invalid parameter error'
  });
th ()に渡されたコールバック中で返される値は、次のチェーン()のコールバックに渡されます.2番目のthn ()コールバックは、1 st thn ()コールバックの結果を受け取ることができました.

約束。all ()


我々がこれまで見た例では、我々のasync呼び出しの順序は重要でした.我々の非同期呼び出しが独立している場合には、私たちは、それぞれの呼び出しの結果を何らかの形で結合する必要があります.all ()
約束.all ()は、複数の約束を非同期で実行しますが、最終的な値を配列で収集します.

let promise1 = add(5, 10);
let promise2 = add(11, 12);
let promise3 = add(7, 8);

//Async execution (faster)
Promise.all([promise1, promise2, promise3])
  .then(function(result){
    console.log(result);// logs [15, 23, 15]
  })
私たちの追加は互いに独立しているので、同期を追加するためにthen ()を使用しません.代わりに、それらは非同期に保たれます.これは実際に同期するよりも速く実行されます.
重要:順序が問題であるか、呼び出しが互いに依存しているなら、私たちはthen ()で我々の呼び出しを同期させるだけです.
//Sync execution (slower), not needed in this case 
//also relies on global state arr

let arr = [];

add(10, 5)
  .then(function(sum1){
    arr.push(sum1);
    return add(11, 12);
  })
  .then(function(sum2){
    arr.push(sum2);
    return add(3, 4)
  })
  .then(function(sum3){
    arr.push(sum3);
    console.log(arr);
    //logs [15, 23 7] the result of all promises that resolved in the chain
    //this result is only available in this scope
  });

console.log(arr);
//logs [] empty array because this log runs asynchronously with the first call to add(). 
//The other promises have not resolved yet.

結論


このポストで、我々は彼らをまとめることによってネストしたコールバックの上でどのように改善するかを示しました.しかし、制限はすべての呼び出しの結果がチェーンの終わりに利用可能であるということです.
いつものように、あなたはこのREPLでこの記事のコードを試すことができます.
とにかくこれを改善することができますか?あなたが固執するならば、私は私がこのシリーズの最終的なポストで話すと約束します.