javascript ES 6新特性のPromise、ES 7 async/await

14950 ワード

s 6が発売されると、Promiseはずっと注目されています.では、なぜPromiseが注目されているのでしょうか?答えはとても簡単で、Promiseはコールバック関数の使い方を最適化しました.もともとは縦の層が必要とされていたアップリケ関数が横方向の呼び出しを実現しました.
まず次のコードを見に行きます.
1 function getData(){
2     setTimeout(()=>{
3         var name = "zhangsan";
4     }, 1000)
5 }
6 
7 getData();
 
上記のコードの中で、非同期時間をシミュレーションしました.一秒後にname=「zhangsan」を出力します.どのようにして私たちがgetData()メソッドを呼び出した時にこのname値を手に入れますか?
1 function getData(){
2     setTimeout(()=>{
3         var name = "zhangsan";
4     }, 1000);
5     return name
6 }
7 
8 console.log(getData()); // ReferenceError: name is not defined
 
結果はエラーが発生しました.この時、getData()関数を実行すると、setTimeoutが非同期で実行するため、まず第5行のreturn nameを実行します.一秒後になってname="zhangsan"を宣言します.だからできます name is not definedの間違い.
その中にリセットをセットTimeoutに入れて実行するという人がいるかもしれません.
1 function getData(){
2     setTimeout(()=>{
3         var name = "zhangsan";
4         return name
5     }, 1000);
6 }
7 
8 console.log(getData()); // undefined
まだname値が取れないので、undefinedのエラーを報告するのは簡単です.getData()を実行する時、方法は戻りません.だからundefinedに報告して、一秒後にsetTimeoutを実行します.
 
以上のエラーで私たちは、setTimeoutが実行されてからnameの値を得ることができます.だから、私たちは実行が終わった後に、再度メロディーでnameの値を取得する必要があります.以下の通りです.
 1 function getData(callback){
 2     setTimeout(()=>{
 3         var name = "zhangsan";
 4         callback(name)
 5     }, 1000)
 6 }
 7 
 8 getData((data)=>{
 9     console.log(data) // zhangsan
10 });
 
私たちはgetData()法の中で一つのコールバック関数を出入りして、setTimeoutが実行終了したらこの方法を呼び出して、name値を入力して、name値を手に入れることができます.ここではES 6のもう一つの特性矢印関数を使って、とりあえずそれ()=>{}とfunction(){}を等価と見なします.
 
上記の方法は私達の問題を解決することができますが、コードの上でもう一つのコールバック関数が必要です.このように見えます.とても友好的ではないので、ES 6はPromiseという特性を提供してくれました.
1 var p = new Promise((resolve, reject) => {
2     setTimeout(() => {
3         var name = "zhangsan";
4         resolve(name)
5     }, 1000)
6 });
7 p.then((data) => {
8     console.log(data);
9 });  // zhangsan
 
上のコードは以下のものと同じです.
 1 function getData(resolve, reject) {
 2     setTimeout(() => {
 3         var name = "zhangsan";
 4         resolve(name)
 5     }, 1000)
 6 }
 7 
 8 var p = new Promise(getData);
 9 
10 p.then((data)=> {
11     console.log(data);
12 });  // zhangsan
Promiseコンストラクタはパラメータとして関数を受け入れています.関数の中には2つのパラメータresoveとrejectがあります.ここで、rejectは実行成功の関数として機能しています.以下のとおりです
 1 function getData(resolve, reject) {
 2     setTimeout(() => {
 3         var name = "zhangsan";
 4         if(Math.random() < .5){
 5             resolve(name)
 6         } else{
 7             reject("   name   ")
 8         }
 9     }, 1000)
10 }
11 
12 var p = new Promise(getData);
13 
14 p.then((data)=> {
15     console.log(data);   // zhangsan
16 },(data)=>{
17     console.log(data);   //    name   
18 }) ;
乱数を指定します.乱数が0.5以下の場合はp.then()の最初の関数、すなわち正しいresoveを使います.乱数が0.5より大きい場合は、2番目の関数、つまり間違ったrejectを使います.
Promiseはthen以外にもcatchの一つの方法を提供しています.
 1 function getData(resolve, reject) {
 2     setTimeout(() => {
 3         var name = "zhangsan";
 4         resolve(name)
 5     }, 1000)
 6 }
 7 
 8 var p = new Promise(getData);
 9 
10 p.then((name)=> {
11     console.log(name);   // zhangsan
12     console.log(age)
13 }).catch((reason)=>{
14     console.log(reason)  // ReferenceError: age is not defined
15 }) ;
上のコードの中で私たちはp.then()の方法で一つのメッセージを出力しましたが、このメッセージは大域的に定義されていませんし、値を伝える方法もありません.もし次のcatch()の方法を書かないなら、報告します. ReferenceErrer:age is not definedは、同時にプログラムが崩壊します. ReferenceError:age is not defined この方法で出力します.プログラムは壊れません.これは私たちがよく使うtry/catchの方法と似ています.
 
ES 7では、もっと便利な非同期操作方法を提供してくれました.以下のとおりです
 1 async function getData() {
 2     return new Promise((resolve, reject) => {
 3         setTimeout(() => {
 4             var name = "zhangsan";
 5             resolve(name)
 6         }, 1000)
 7     })
 8 }
 9 
10 async function test() {
11     var data = await getData();
12     console.log(data);
13 }
14 
15 test();  // zhangsan
前のコードを上のように変更しました.出力結果は相変わらずzhangsanです.ここでasync/awaitの組み合わせを使っています.上のコードを簡略化します.
 1 async function getData() {
 2     var name = "zhangsan";
 3     return name;
 4 }
 5 
 6 console.log(getData());  // Promise { 'zhangsan' }
 7 
 8 async function test(){
 9     var data = await getData();
10     console.log(data);
11 }
12 
13 test();  // zhangsan
 
私たちはfunction getData(){}の前にasyncのフィールドを追加しました.この関数は非同期関数として認定されました.そして、getData()を呼び出す方法の前にawaitのフィールドを追加します.これは非同期操作という意味です.の関数にsetTimeoutの非同期方法を追加した後も、非同期方法が実行された後に呼び出しを行うと、name="zhangsan"の値が得られます.