ES6 版 async/await を改善しました
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ GeneratorFunction のメソッドに aync を追加
◆ ES7 のと文字数的にはほぼ変わらない
◆ ES7 のと文字数的にはほぼ変わらない
本家
もう正式?に決まってるのか知らないですけど こういう書き方をするのが ES7 で実装予定なものですasync function async_sample(val){
await wait(3000)
console.log("after 3 seconds")
console.log(val)
}
async_sample("abc")
await wait(3000)
console.log("after 3 seconds")
console.log(val)
}
async_sample("abc")
1回目
function* async_sample(val){
yield afunc(wait, 3000)
console.log("after 3 seconds")
console.log(val)
}
acall(aync_sample, "abc")
yield afunc(wait, 3000)
console.log("after 3 seconds")
console.log(val)
}
acall(aync_sample, "abc")
afunc を待機したい非同期処理の呼び出しで使って 非同期処理を含む関数の呼び出しでは acall を使っていました
さらに Promise ではなくコールバックです
あまり良いとはいえないです
2回目
function async_sample(){
return async(arguments, function*(val){
yield wait(3000)
console.log("after 3 second")
console.log(val)
})
}
async_sample("abc")
return async(arguments, function*(val){
yield wait(3000)
console.log("after 3 second")
console.log(val)
})
}
async_sample("abc")
呼び出し側はシンプルになりましたが 非同期処理を含む関数の定義がちょっとめんどうになっています
ジェネレータを内側に持っていて外から見ると普通の関数です
あと Promise 化されています
3回目(今回)
function* async_sample(val){
yield wait(1000)
console.log("after 1second")
console.log(val)
}
async_sample.async("abc")
yield wait(1000)
console.log("after 1second")
console.log(val)
}
async_sample.async("abc")
本来の async/await でも非同期処理を含む関数にわかりやすく async というキーワードをつけてるのでそれに習って 関数の定義はジェネレータにして外から見ても 「*」 がついててわかりやすくなっています
代わりに呼び出しの時に少しコードが増えました
1回目のような関数にジェネレータを渡す方法では 引数に本来の引数とジェネレータが混ざって気持ち悪いので async メソッドをジェネレータに持たせることにしています
3 回目のコードを動かすための用意しておくコード
;(function*(){}).constructor.prototype.async = function(...args){
return new Promise((resolve, reject) => {
var ite = this(...args)
!function recur(pre_value){
var ret = ite.next(pre_value)
ret.done ? resolve(ret.value) : ret.value.then(recur)
}()
})
}
function wait(msec){
return new Promise((resolve, reject) => {
setTimeout(resolve, msec)
})
}
return new Promise((resolve, reject) => {
var ite = this(...args)
!function recur(pre_value){
var ret = ite.next(pre_value)
ret.done ? resolve(ret.value) : ret.value.then(recur)
}()
})
}
function wait(msec){
return new Promise((resolve, reject) => {
setTimeout(resolve, msec)
})
}