async/awaitを理解する


ES 7が提案したasync関数は、JavaScriptが非同期動作に対して最終的な解決策を持つようになりました.No more calback hell.async関数は、Generator関数のシンタックス飴です.キーワードasyncを用いて表され、非同期は関数内部でawaitを使用して表される.Generatorに比べて、Async関数の改善は以下の4点にある.
  • は、アクチュエータを内蔵する.Generator関数の実行は、アクチュエータに依存する必要があります.Aysncは、関数自体がアクチュエータを備えています.呼び出しは、通常の関数の呼び出しと同じです.
  • より良い意味.asyncおよびawaitは、*およびyieldに比べてより語義化された
  • である.
  • より広い適用性.coモジュールは、yieldコマンドの後はThunk関数またはPromiseオブジェクトのみとすることを約束しています.async関数のawaitコマンドの後は、Promiseまたは元のタイプの値(Number、string、bootlean)
  • とすることができる.
  • の戻り値はPromiseです.async関数戻り値はPromiseオブジェクトであり、Generator関数が返したIteratorオブジェクトよりも便利であり、then()方法を直接使用して
  • を呼び出すことができる.
    Asyncと他の非同期操作の対比
    まず、Fetch方法を定義し、github userの情報を取得する.
    function fetchUser() { 
        return new Promise((resolve, reject) => {
            fetch('https://api.github.com/users/superman66')
            .then((data) => {
                resolve(data.json());
            }, (error) => {
                reject(error);
            })
        });
    }
    Promise方式
    /**
     * Promise   
     */
    function getUserByPromise() {
        fetchUser()
            .then((data) => {
                console.log(data);
            }, (error) => {
                console.log(error);
            })
    }
    getUserByPromise();
    Promiseの方式はcalback hellを解決しましたが、この方式はPromiseのthen()方法に満ちています.処理の流れが複雑であれば、全セグメントのコードはthenに満ちています.語義化が明確ではなく、コードフローは実行フローをよく表していません.Generator方式
    /**
     * Generator   
     */
    function* fetchUserByGenerator() {
        const user = yield fetchUser();
        return user;
    }
    
    const g = fetchUserByGenerator();
    const result = g.next().value;
    result.then((v) => {
        console.log(v);
    }, (error) => {
        console.log(error);
    })
    Generatorの方式はPromiseのいくつか問題を解決して、流れは更に直観的で、語義化します.しかし、Generatorの問題は、関数の実行は、毎回g.next()によって実行される必要があることである.async方式
    /**
     * async   
     */
     async function getUserByAsync(){
         let user = await fetchUser();
         return user;
     }
    getUserByAsync()
    .then(v => console.log(v));
    async関数は、上記の2つの方法の問題を完璧に解決した.流れがはっきりしていて、直観的で、意味がはっきりしています.非同期プロセスは操作同期フローのようです.同時にasync関数は、実行時に手動でロードする必要がありません.
    構文
    async関数はPromiseオブジェクトに戻ります.async関数内部returnの戻り値.then方法のコールバック関数のパラメータになります.
    async function  f() {
        return 'hello world'
    };
    f().then( (v) => console.log(v)) // hello world
    async関数の内部に異常があると、戻ってきたPromiseオブジェクトの状態がreject状態になります.投げられたエラーは、catch方法のコールバック関数によって受信される.
    async function e(){
        throw new Error('error');
    }
    e().then(v => console.log(v))
    .catch( e => console.log(e));
    async関数が戻ってきたPromiseオブジェクトは、内部のawaitコマンドのPromiseオブジェクトが実行されるまで、状態が変化します.
    すなわち、async関数内部の非同期動作が全部実行された場合にのみ、then方法のコールバックが実行される.
    const delay = timeout => new Promise(resolve=> setTimeout(resolve, timeout));
    async function f(){
        await delay(1000);
        await delay(2000);
        await delay(3000);
        return 'done';
    }
    
    f().then(v => console.log(v)); //   6s     'done'
    通常、await命令の後に続くのはPromiseです.そうでないと、即戦力に変換されるPromiseも次のようになります.
    async function  f() {
        return await 1
    };
    f().then( (v) => console.log(v)) // 1
    リターンがrejectの状態である場合、catch方法によって捕捉される.
    Async関数のエラー処理async関数の文法は難しくないです.エラー処理では難しいです.まず次の例を見てみます.
    let a;
    async function f() {
        await Promise.reject('error');
        a = await 1; //    await      
    }
    f().then(v => console.log(a));
    上記のように、async関数のうちの1つがawaitでreject状態が発生している限り、後のawaitは実行されない.解決策:try/catchを追加することができます.
    //      
    let a;
    async function correct() {
        try {
            await Promise.reject('error')
        } catch (error) {
            console.log(error);
        }
        a = await 1;
        return a;
    }
    
    correct().then(v => console.log(a)); // 1
    awaitが複数あるなら、それを全部try/catchに置くことができる.
    プロジェクトでどのように使うか?
    相変わらずbabelによって使用されている.presetsstage-3に設定するだけでいいです.インストール依存:
    npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime
    修正.babelrc:
    "presets": ["es2015", "stage-3"],
    "plugins": ["transform-runtime"]
    これにより、プロジェクトにasync関数を使用することができます.
    Frther Reading
  • Understanding JavaScript’s async await
  • Aync/Await-Best Practices in Aynchronous Programming
  • 非同期動作とAsync関数
  • 最初の文章は私のブログです.chenhuichao.com