自分は主にはRubyのサーバーサイドエンジニアなのですが、とはいえスタートアップということもあり時々Node.jsでの開発ややReact.jsを書くことがあります。
でその度に
1 久しぶりに見たjavascriptの非同期処理の書き方を見る
↓
2 あれ?thenとかPromiseとかなんやったかなー?忘れたもう一回ちゃんと復習(かなり時間かかる)
↓
3 しっかり解説されている記事を見て、あーなるほど思い出したとなる
↓
4 時間が経つ
↓
1に戻る
を繰り返しているので2の時間を削減すべく、暫く見ると思い出すメモコードを書きました。
ちなみにじっくり理解したい方は3の記事が非常におすすめです!
このコードも3の記事を参考にさせていただいております。ありがとうございます。
以下はコードです。
// Normal callback
// 関数を引数として渡して実行する
// ネストすると所謂コールバック地獄が起きる
function func_with_callback(callback) {
let [data, err] = ['data', null] // 実際はここは何かの非同期処理 成功時
// let [data, err] = [null, 'error'] // 失敗時
callback(data, err)
}
func_with_callback(function(data, err){
if(data){
console.log(data)
} else{
console.log(err)
}
})
/***
Promise
callback地獄にならないための書き方
呼び出され関数はPromiseオブジェクトを返す
Promiseは3つの状態
* Pending 未実行/実行中
* Fulfilled 処理成功時
* Rejected 処理失敗
を持っており、
Promiseは非同期処理の結果をcallback関数の引数ではなく
成功時 resolve(args) ⇨ onFulfilled(args)関数が実行
失敗時 reject(args) ⇨ onRejected(args)関数が実行
されることで処理の結果を戻す。
resolve時は then
reject時は catch
に渡される関数に処理結果が引数として渡される
Promiseを使うことで
foo_func()
.then(baz_func)
.then(baz_func)
.catch(err)
のように書けてコールバックを回避できる
***/
function func_with_promise(){
return new Promise(function(resolve, reject){ // => status: Pending 作られた時点ではPending
let [data, err] = ['data', null] // 実際はここは何かの非同期処理 成功時
// let [data, err] = [null, 'error'] // 失敗時
if(data){
resolve(data) // => status:Fulfilled onFulfilledが呼ばれる
} else {
reject(err) // => status:Rejected onRejectedが呼ばれる
}
})
}
func_with_promise()
.then(function onFulfilled(data){ // onFulfilled
console.log(data)
})
.catch(function onRejected(err){ // onRejected
console.log(err)
})
/***
Async/await
asyncで定義した関数は呼び出し時にPromiseを返す。
関数内で
値をreturnするとresolve
エラーが起きたらrejectする
***/
async function func_with_async(){
let [data, err] = ['data', null] // 実際はここは何かの非同期処理 成功時
return data // 値をreturnした場合はresolve(data)
// let [data, err] = [null, 'error']
// if (err) throw err // エラーが起きた場合はreject(err)
}
// async functionもPromiseを返すのでthenでチェーン出来る
func_with_async().then(function(data){
console.log(data)
}).catch(function(err){
console.log(err)
})
// async functionの中ではawait出来る
async function await_func(){
try {
res = await func_with_async() // awaitはasync関数内でしか使えない
console.log(res)
} catch(err){
console.log(err)
}
}
await_func()
半分は自分用ですが、同じような境遇の方の役に立つか、フロントエンドの詳しい方から何かあればご指摘いただけるとうれしいです。