async/await分析
6201 ワード
async/await分析
分析
まず、
Generator yield Thunk
自動フロー管理
JavaScript
はシングルスレッドであり、同期ブロッキングによる負の影響を避けるために、非同期非ブロッキング機構を導入したが、非同期実行の解決策については最初のコールバック関数からES6
のPromise
オブジェクトおよびGenerator
関数まで、毎回改善されているが、米中では不十分であり、それらは追加の複雑性を持っている.ES7
にasync/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
の関数を使用して、上記と同じ例を実現すると、Thunk
をasync
の関数の右端に配置するだけで*
を見ることができる.await
をyield
に置き換えたので、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 Thunk
、Generator 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