Promise入門の詳細と基本的な使い方

17595 ワード

非同期呼び出し
非同期
JavaScriptの実行環境はシングルスレッドです.
シングルスレッドとは、JSエンジンでJavaScriptコードを解釈し実行するスレッドが一つしかないということです.つまり一回に一つのタスクを完成することができます.このタスクを実行してから次のタスクを実行できます.ブロックは他のタスクを実行します.このタスクはメインスレッドと呼ぶことができます.
非同期モードは、複数のタスクを一緒に実行することができる.
一般的な非同期モードは以下のようなものがあります.
  • タイマー
  • インターフェース呼び出し
  • イベント関数
  • 今日のこの文章はインターフェースの呼び出しに重点を置いて話します.インターフェースの呼び出しで、Promiseを重点的に話してください.
    インターフェース呼び出しの方式
    jsでよく見られるインターフェースの呼び出し方法は、以下のようなものがあります.
  • 原生ajax
  • jQueryに基づくajax
  • Fetch
  • Promise
  • axios
  • 複数の非同期呼び出しの依存分析
  • による非同期呼び出しの結果、順序が同期されない場合があります.
  • 非同期呼出しの結果に依存がある場合、ネストが必要となる.
  • ES 5において、多層ネストコールを行うと、コードレベルが多すぎて、メンテナンスと二次開発が難しくなります.そして地獄に戻る問題を引き起こす.ES 6のPromiseはこの二つの問題を解決できます.
    Promise概要
    Promiseの紹介と長所
    ES 6のPromiseは非同期プログラミングの一つです.文法的には、Promiseはオブジェクトであり、非同期操作のメッセージを取得することができます.
    Promiseオブジェクトは、非同期動作を同期の流れで表現することができます.Promiseを使うには主に以下のようなメリットがあります.
  • は地獄の問題をうまく解決できます.
  • 文法はとても簡潔です.Promiseオブジェクトは、非同期動作をより容易に制御するための簡潔なAPIを提供する.
  • 地獄の例を調べる
    野菜を買ったり、料理を作ったり、食器を洗ったりするのは例外です.
    しかし、実際のシーンでは、実際の操作の流れは、料理が成功してから、料理ができます.料理が成功してから、食器を洗い始めます.この中は多层仕挂けのコール、つまりコールバック地狱に関わっています.
    Promiseの基本的な使い方
    (1)newを用いてPromiseオブジェクトを具体化し、Promiseの構造関数で一つのパラメータを伝達する.このパラメータは非同期タスクを処理する関数です.
    (2)2つのパラメータが入ってきます.レスオーブとrejectは、それぞれ非同期が成功した後のコールバック関数と非同期が失敗した後のコールバック関数を表します.
    (3)promise.then()処理により結果を返す.ここのpはPromiseの例です.
    コードの例は以下の通りです.
    
    
        
            
            
            Document
        
        
            
                //    :model      
                const promise = new Promise((resolve, reject) => {
                    //        (  ajax     。          )
                    setTimeout(function() {
                        var data = { retCode: 0, msg: 'qianguyihao' }; //        
                        if (data.retCode == 0) {
                            //          
                            resolve(data);
                        } else {
                            //          
                            reject({ retCode: -1, msg: 'network error' });
                        }
                    }, 100);
                });
    
                //    :        。    data      resolve   reject     ,           
                promise.then(data => {
                    //   resolve       
                    console.log(data);
                }).catch(data => {
                    //   reject       
                    console.log(data);
                });
            
        
    
    
    
    上のコードでは、インターフェースから返されたデータdata.retCodeの値が異なると、revoveを実行するかもしれないし、rejectを実行するかもしれない.これはあなた自身の業務によって決定されます.
    promise対象の3つの状態(了解すればいい)
  • 初期化状態(待ち状態):pending
  • 成功状態:fullfilled
  • 失敗状態:reject
  • (1)new Promise()が実行されると、promiseオブジェクトの状態はpendingに初期化され、この状態は初期化状態である.new Promise()この行のコードは、括弧内の内容が同期して実行されます.括弧の中で一つのfunctionを定義して、functionは二つのパラメータがあります.以下のとおりです
  • 要求が成功したら、resove()が実行され、このとき、promiseの状態が自動的にfullfilledに修正される.
  • リクエストが失敗したら、reject()を実行します.このとき、promiseの状態は自動的にreject
  • に変更されます.
    (2)promise.then()方法は、括弧の中に2つのパラメータがあり、それぞれ2つの関数function 1とfunction 2を表しています.
  • promiseの状態がfullfilledであれば、function 1の内容
  • を実行します.
  • promiseの状態がrejectiedであれば、functions 2の内容
  • を実行します.
    また、reolve()とreject()の2つの方法は、promise.then()にパラメータを伝えることができます.
    完全コードの例は以下の通りです.
        let promise = new Promise((resolve, reject) => {
            //    ,   pending
            console.log('111');  //        
            //        (    ,      ,  ajax   or      )
            if (   ajax    ) {
                console.log('333');
                resolve('haha');//       ,  resolve(),  ,promise          fullfilled
            } else {
                reject('555');//       ,  reject(),  ,promise          rejected
            }
        })
        console.log('222');
    
        //  promise then()
        promise.then((successMsg) => {
                //  promise    fullfilled,        
                console.log(successMsg, '   ');
            }
            , (errorMsg) => {
                //  promise    rejected,        
                console.log(errorMsg, '   ');
    
            }
        )
    
    Promiseに基づいて何度もAjax要求を処理する(チェーンコール)【重要】
    実際の開発では、私たちはしばしば複数のインターフェースを同時に要求する必要があります.例えば、 1のデータdata1を要求した後、data1のデータに基づいて要求インターフェース2を継続し、data2を取得する必要がある.次いで、data2のデータに基づいて、インターフェース3を要求し続ける.
    このような場面は実はインターフェースの多層ネスト呼び出しです.プロミスがあったら、私たちは多層ネストを線形に表記することができます.とても優雅です.
    つまり、Promiseは本来の多層ネスト呼び出しをチェーン呼び出しに変更することができます.
    コード例:(複数のAjax要求、チェーン呼び出し)
    
    
        
            
            
            Document
        
        
            
                /*
                    Promise  Ajax  
                */
                function queryData(url) {
                    var promise = new Promise((resolve, reject) => {
                        var xhr = new XMLHttpRequest();
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState != 4) return;
                            if (xhr.readyState == 4 && xhr.status == 200) {
                                //       
                                resolve(xhr.responseText); // xhr.responseText          
                            } else {
                                //       
                                reject('      ');
                            }
                        };
                        xhr.responseType = 'json'; //          
                        xhr.open('get', url);
                        xhr.send(null); //     
                    });
                    return promise;
                }
                //     ajax        
                queryData('http://localhost:3000/api1')
                    .then(
                        data1 => {
                            console.log(JSON.stringify(data1));
                            //      1 ,      2
                            return queryData('http://localhost:3000/api2');
                        },
                        error1 => {
                            console.log(error1);
                        }
                    )
                    .then(
                        data2 => {
                            console.log(JSON.stringify(data2));
                            //      2 ,      3
                            return queryData('http://localhost:3000/api3');
                        },
                        error2 => {
                            console.log(error2);
                        }
                    )
                    .then(
                        data3 => {
                            //     3     
                            console.log(JSON.stringify(data3));
                        },
                        error3 => {
                            console.log(error3);
                        }
                    );
            
        
    
    
    
    上記の例はとても古典的で、何回も見なければなりません.
    returnの関数は値を返します.
    リターンの後の戻り値は、2つの場合があります.
  • ケース1:Promiseのインスタンスオブジェクトに戻る.返された例のオブジェクトは、次のthenを呼び出します.
  • の場合2:普通の値を返します.返した普通の値は次のthenに直接渡され、thenパラメータの関数のパラメータでこの値を受信します.
  • 上の二つの状況について詳しく説明します.
    ケース1:Promiseのインスタンスオブジェクトに戻る
    例えば、次のような例があります.
    
    
        
            
            
            Document
        
        
            
                /*
                    Promise  Ajax  
                */
                function queryData(url) {
                    return new Promise((resolve, reject) => {
                        var xhr = new XMLHttpRequest();
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState != 4) return;
                            if (xhr.readyState == 4 && xhr.status == 200) {
                                //       
                                resolve(xhr.responseText);
                            } else {
                                //       
                                reject('      ');
                            }
                        };
                        xhr.responseType = 'json'; //          
                        xhr.open('get', url);
                        xhr.send(null); //     
                    });
                }
                //     ajax        
                queryData('http://localhost:3000/api1')
                    .then(
                        data1 => {
                            console.log(JSON.stringify(data1));
                            return queryData('http://localhost:3000/api2');
                        },
                        error1 => {
                            console.log(error1);
                        }
                    )
                    .then(
                        data2 => {
                            console.log(JSON.stringify(data2));
                            //     return,     Promise     
                            return new Promise((resolve, reject) => {
                                resolve('qianguyihao');
                            });
                        },
                        error2 => {
                            console.log(error2);
                        }
                    )
                    .then(data3 => {
                        console.log(data3);
                    });
            
        
    
    
    
    ケース2:普通の値を返します.
    
    
        
            
            
            Document
        
        
            
                /*
                    Promise  Ajax  
                */
                function queryData(url) {
                    return new Promise((resolve, reject) => {
                        var xhr = new XMLHttpRequest();
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState != 4) return;
                            if (xhr.readyState == 4 && xhr.status == 200) {
                                //       
                                resolve(xhr.responseText);
                            } else {
                                //       
                                reject('      ');
                            }
                        };
                        xhr.responseType = 'json'; //          
                        xhr.open('get', url);
                        xhr.send(null); //     
                    });
                }
                //     ajax        
                queryData('http://localhost:3000/api1')
                    .then(
                        data1 => {
                            console.log(JSON.stringify(data1));
                            return queryData('http://localhost:3000/api2');
                        },
                        error1 => {
                            console.log(error1);
                        }
                    )
                    .then(
                        data2 => {
                            console.log(JSON.stringify(data2));
                            //      
                            return 'qianguyihao';
                        },
                        error2 => {
                            console.log(error2);
                        }
                    )
                    /*
                                    ,  ,    then       ?
                           :              promise  ,      then,            。
                    */
                    .then(data3 => {
                        //     data3          'qianguyihao'
                        console.log(data3);
                    });
            
        
    
    
    
    Promiseの通常のAPI:実例の方法【重要】
    Promiseが保有するAPIは、以下のような実例的な方法を提供する.
  • promise.then():非同期タスクの正常な結果を取得する.
  • promise.catch():非同期タスクの異常結果を取得する.
  • promise.finaly():非同期タスクは成功するかどうかに関わらず、実行されます.
  • コードの例は以下の通りです.
    書き方1:
    
    
        
            
            
            Document
        
        
            
                function queryData() {
                    return new Promise((resolve, reject) => {
                        setTimeout(function() {
                            var data = { retCode: 0, msg: 'qianguyihao' }; //        
                            if (data.retCode == 0) {
                                //          
                                resolve(data);
                            } else {
                                //          
                                reject({ retCode: -1, msg: 'network error' });
                            }
                        }, 100);
                    });
                }
    
                queryData()
                    .then(data => {
                        //   resolve       
                        console.log('       ,   ');
                        console.log(data);
                    })
                    .catch(data => {
                        //   reject       
                        console.log('       ,   ');
                        console.log(data);
                    })
                    .finally(() => {
                        console.log('          ,     ');
                    });
            
        
    
    
    
    書き方2:(上記の書き方と1は等価)
    
    
        
            
            
            Document
        
        
            
                function queryData() {
                    return new Promise((resolve, reject) => {
                        setTimeout(function() {
                            var data = { retCode: 0, msg: 'qianguyihao' }; //        
                            if (data.retCode == 0) {
                                //          
                                resolve(data);
                            } else {
                                //          
                                reject({ retCode: -1, msg: 'network error' });
                            }
                        }, 100);
                    });
                }
    
                queryData()
                    .then(
                        data => {
                            //   resolve       
                            console.log('       ,   ');
                            console.log(data);
                        },
                        data => {
                            //   reject       
                            console.log('       ,   ');
                            console.log(data);
                        }
                    )
                    .finally(() => {
                        console.log('          ,     ');
                    });
            
        
    
    
    
    注意:書き方1と書き方2の役割は完全に等価です.ただし、書き方2はcatchのコードをthenの中の第二パラメータとして使うだけです.
    Promiseの一般API:対象方法【重要】
    Promiseが持参するAPIは、以下のような対象方法を提供しています.
  • Promise.all():複数の非同期タスクを同時に処理し、すべてのタスクが成功してこそ、結果が得られます.
  • Promise.race():複数の非同期タスクを同時に処理し、一つのタスクが成功すれば、結果が得られます.
  • 詳しく紹介します.
    Promise.allコード例
    コードの例:
    
    
        
            
            
            Document
        
        
            
                /*
                     Promise     
                */
                function queryData(url) {
                    return new Promise((resolve, reject) => {
                        var xhr = new XMLHttpRequest();
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState != 4) return;
                            if (xhr.readyState == 4 && xhr.status == 200) {
                                //       
                                resolve(xhr.responseText);
                            } else {
                                //       
                                reject('     ');
                            }
                        };
                        xhr.open('get', url);
                        xhr.send(null);
                    });
                }
    
                var promise1 = queryData('http://localhost:3000/a1');
                var promise2 = queryData('http://localhost:3000/a2');
                var promise3 = queryData('http://localhost:3000/a3');
    
                Promise.all([promise1, promise2, promise3]).then(result => {
                    console.log(result);
                });
            
        
    
    
    Promise.race()コード例
    コードの例:
    
    
        
            
            
            Document
        
        
            
                /*
                     Promise     
                */
                function queryData(url) {
                    return new Promise((resolve, reject) => {
                        var xhr = new XMLHttpRequest();
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState != 4) return;
                            if (xhr.readyState == 4 && xhr.status == 200) {
                                //       
                                resolve(xhr.responseText);
                            } else {
                                //       
                                reject('     ');
                            }
                        };
                        xhr.open('get', url);
                        xhr.send(null);
                    });
                }
    
                var promise1 = queryData('http://localhost:3000/a1');
                var promise2 = queryData('http://localhost:3000/a2');
                var promise3 = queryData('http://localhost:3000/a3');
    
                Promise.race([promise1, promise2, promise3]).then(result => {
                    console.log(result);
                });
            
        
    
    
    これらの内容を知ると、Promiseの基本的な使い方が分かります.