async/await分析

6201 ワード

async/await分析JavaScriptはシングルスレッドであり、同期ブロッキングによる負の影響を避けるために、非同期非ブロッキング機構を導入したが、非同期実行の解決策については最初のコールバック関数からES6PromiseオブジェクトおよびGenerator関数まで、毎回改善されているが、米中では不十分であり、それらは追加の複雑性を持っている.ES7async/awaitが導入されるまで、抽象的な底層動作機構を理解する必要があり、複数のPromiseを使用するときの同期挙動を簡略化することができ、プログラミングするときにも、この動作が非同期動作であるかどうかに関心を持たなくてもよい.
分析
まず、async/awaitを使用して非同期動作のセットを実行し、入れ子を戻す必要もないし、複数のthen方法を書く必要もない.使用上、これ自体が同期動作だとさえ思っている.もちろん、本使用ではawait文を try...catchコードブロックに置くべきである.awaitコマンドの後のPromiseオブジェクトであるので、実行結果はrejectedであるかもしれない.
function promise(){
    return new Promise((resolve, reject) => {
       var rand = Math.random() * 2; 
       setTimeout(() => resolve(rand), 1000);
    });
}

async function asyncFunct(){
    var r1 = await promise();
    console.log(1, r1);
    var r2 = await promise();
    console.log(2, r2);
    var r3 = await promise();
    console.log(3, r3);
}

asyncFunct();
async/awaitは、実際にはGeneratorの関数のシンタックスキャンディーであり、Promisesと同様の構造化エコーを実現するasync/awaitは、Generatorの関数とPromiseの関数を組み合わせたものであり、以下にGeneratorの関数を使用して、上記と同じ例を実現すると、Thunkasyncの関数の右端に配置するだけで*を見ることができる.awaityieldに置き換えたので、async/awaitは実際にはGeneratorの関数のシンタックス飴であり、ここで唯一の違いは、1つのフローの自動管理関数runを実装し、async/awaitは実行器を内蔵しており、この例の実現については後述する.対照的に、asyncおよびawaitは、*およびyieldよりも意味がはっきりしており、asyncは関数内に非同期的な動作があることを示し、awaitは、後に続く表現が結果を待つ必要があることを示している.
function thunkFunct(index){
    return function f(funct){
        var rand = Math.random() * 2;
        setTimeout(() => funct(rand), 1000)
    }
}

function* generator(){ 
    var r1 = yield thunkFunct();
    console.log(1, r1);
    var r2 = yield thunkFunct();
    console.log(2, r2);
    var r3 = yield thunkFunct();
    console.log(3, r3);
}

function run(generator){
    var g = generator();

    var next = function(data){
        var res = g.next(data);
        if(res.done) return ;
        // console.log(res.value);
        res.value(next);
    }

    next();
}

run(generator);
実現するasync関数には実行器が内蔵されており、関数実行の自動フロー管理を実現することができ、Generator yield ThunkGenerator yield Promiseを介して自動フロー管理を実現するためには、Generator関数およびThunk関数またはPromiseオブジェクトを作成して実行関数に入るだけで、async/awaitと同様の効果が実現できる.
Generator yield Thunk
自動フロー管理run関数は、まず第一に、next()メソッドを呼び出したときに、パラメータが入ってきたら、前の実行されたyield文の左の変数にこのパラメータが伝達されます.この関数では、nextが初めて実行されたときにパラメータが渡されませんでした.第一のyield上にも、変数を受信するステートメントがありません.パラメータを渡す必要はなく、次にこのジェネレータ関数が実行されたかどうかを判断し、ここでは実行が完了していない場合、カスタマイズされたnext関数をres.valueに入力します.このとき、私たちはカスタムres.valueの関数を転送した後、f(funct){...}の実行権限をnextの関数に与え、この関数が非同期タスクを実行した後、コールバック関数を実行し、このコールバック関数でジェネレータの次のnext方法をトリガし、このfの方法はパラメータを伝達するものである.上述したパラメータが入った後に、前のバーで実行されたnext文の左の変数に渡されると、この実行において、このパラメータ値はnextに渡され、次いでyieldが実行され、ジェネレータ関数が動作を終了するまで往復され、フローの自動管理が実現される.
function thunkFunct(index){
    return function f(funct){
        var rand = Math.random() * 2;
        setTimeout(() => funct(rand), 1000)
    }
}

function* generator(){ 
    var r1 = yield thunkFunct();
    console.log(1, r1);
    var r2 = yield thunkFunct();
    console.log(2, r2);
    var r3 = yield thunkFunct();
    console.log(3, r3);
}

function run(generator){
    var g = generator();

    var next = function(data){
        var res = g.next(data);
        if(res.done) return ;
        // console.log(res.value);
        res.value(next);
    }

    next();
}

run(generator);
Generator yield Promiser1関数を使用してフロー自動管理を行うことに対して、nextを使用して比較的簡単に実現することができ、Thunk例は前回のコールバックがいつ実行されるかを知ることができ、Promise方法によって次のPromiseを起動し、継続的に実行することができ、これによってフローの自動管理が実現される.
function promise(){
    return new Promise((resolve,reject) => {
        var rand = Math.random() * 2;
        setTimeout( () => resolve(rand), 1000);
    })
}

function* generator(){ 
    var r1 = yield promise();
    console.log(1, r1);
    var r2 = yield promise();
    console.log(2, r2);
    var r3 = yield promise();
    console.log(3, r3);
}

function run(generator){
    var g = generator();

    var next = function(data){
        var res = g.next(data);
        if(res.done) return ;
        res.value.then(data => next(data));
    }

    next();
}

run(generator);
//              
function promise(){
    return new Promise((resolve,reject) => {
        var rand = Math.random() * 2;
        setTimeout( () => resolve(rand), 1000);
    })
}

function* generator(){ 
    var r1 = yield promise();
    console.log(1, r1);
    var r2 = yield promise();
    console.log(2, r2);
    var r3 = yield promise();
    console.log(3, r3);
}

function run(generator){
    return new Promise((resolve, reject) => {
        var g = generator();
        
        var next = function(data){
            var res = null;
            try{
                res = g.next(data);
            }catch(e){
                return reject(e);
            }
            if(!res) return reject(null);
            if(res.done) return resolve(res.value);
            Promise.resolve(res.value).then(data => {
                next(data);
            },(e) => {
                throw new Error(e);
            });
        }
        
        next();
    })
   
}

run(generator).then( () => {
    console.log("Finish");
});
毎日の問題
https://github.com/WindrunnerMax/EveryDay
参照
https://segmentfault.com/a/1190000007535316
http://www.ruanyifeng.com/blog/2015/05/co.html
http://www.ruanyifeng.com/blog/2015/05/async.html