目的
- 処理待ちの実装で使う非同期処理の書き方を把握するメモ
- 最小限の説明、最小限のサンプルで把握する
- とりあえず、意図通りに動く、がゴール
使途
- ファイル保存処理、APIコール、DBアクセス等の結果を待ってから、次の処理を行う必要がある場合
コードサンプル
// 1. 利用するコード
syTst()
// 2. 同期・非同期処理を制御するコード
syTst = async() =>{
console.log("AsyncTest実行1")
const result = await this.myPromise();
console.log("AsyncTest5")
const result2 = await this.myPromise2();
console.log("AsyncTest実行完了")
}
// 3. 利用されるコード
myPromise = () => {
return new Promise(function(resolve) {
setTimeout(function() { resolve(console.log("myPromise1")) }, 5000)
})
}
myPromise2 = () => {
return new Promise(function(resolve) {
setTimeout(function() { resolve(console.log("myPromise2")) }, 10000)
})
}
- 動作
- syTst()を実行する
- myPromise()、myPromise2、が順番に実行される。
- それぞれのメソッドは待機時間があり、結果は5秒、10秒ずつたってから返す
考え方
// 1. 利用するコード
syTst()
- 時間のかかる処理等を実行する場所
// 2. 同期・非同期処理を制御するコード
syTst = async() =>{
console.log("AsyncTest実行1")
const result = await this.myPromise();
console.log("AsyncTest5")
const result2 = await this.myPromise2();
console.log("AsyncTest実行完了")
}
- await がついたメソッドが完了するのを待ってから次を実行する
- awaitは async() が付加されたメソッドでしか利用できない(同期・非同期制御はこのメソッド内で行う)
- 即ち、結果を待ってから、画面を切り替えるなどの処理は、1. のコードではなく、 2. のこのコード内で行う必要がある
// 3. 利用されるコード
myPromise = () => {
return new Promise(function(resolve) {
setTimeout(function() { resolve(console.log("myPromise1")) }, 5000)
})
}
- 実行する処理 例では5秒待機してから完了する
- 返す値は、Promiseオブジェクトを返す
- 戻す値は 上の例では
resolve
関数に引数として渡す new Promise(function(ここで設定した関数) {
- 同名のメソッド
resolve(console.log("myPromise1")
から結果を呼び出し元に返す - 留意事項
- awaitのメソッドが「終わった」と判定されるのはresolveメソッドを実行したとき。例えば例でいうと、setTimeOutの外でresorveすると、5秒を待たずに終了し次の処理に入る
理解のための資料
【JavaScript入門】5分で理解!async / awaitの使い方と非同期処理の書き方
https://www.sejuku.net/blog/69618
async/await 入門(JavaScript)
https://qiita.com/soarflat/items/1a9613e023200bbebcb3
例
画面ボタン操作で、入力項目をDBに入れ、結果に応じて画面遷移する
- react-native
- 事例はプロフィール編集画面
- 画面入力は、stateに設定されている
- stateをIfProxyというDB操作を一任するクラスでFirebaseに登録する
- 成功した場合は、OKという文字列を画面に返す
- 画面はOKを確認したら、VID2という画面に遷移する、確認できなければ遷移しない
画面側
// 登録ボタンを押下
doAction = () =>{
console.log("プロフィールを登録する");
// 永続化
this.asyncResistration();
}
// 同期処理 プロフィール情報更新
asyncResistration = async () =>{
updateProfileDao = new IfProxy()
const result = await updateProfileDao.updateProfile(this.state)
console.log("updateProvile処理戻り")
console.log(result)
if(result=="OK") {
// 申請完了 ホームに戻る
const { navigation } = this.props;
navigation.reset({
index: 0,
routes: [{name: 'VID2'}]
})
} else{
this.state.errorFlg = true;
this.state.errorMessage = result+"";
}
}
データ操作オブジェクトがわ
updateProfile(newData){
// 完了したら戻すため、処理をPromiseの中にする
// returnではなく、resolveで終了しその引数に返す
return new Promise((resolve) => {
console.log("認証データ更新")
// 認証ユーザデータの更新
user.updateProfile({
accountType:newData.accountType,
point:newData.point,
sex:newData.sex,
menChecked:newData.menChecked,
womenChecked:newData.womenChecked
})
.then(function() {
resolve("OK");
})
.catch(function(error) {
console.log("Error getting documents: ",error);
resolve("NG");
});
})
}).catch(function(error) {
// 登録に失敗
console.log("===DB登録に失敗===")
resolve("NG");
});
}