現在関わっているプロジェクトでNode.jsを使って開発しています。
その過程でハマったこと、今回はasync/await・Promiseについての記事になります。
といってもNode.jsを使ったことのない人もいると思うので簡単にNodeの非同期処理について紹介してから、ハマったポイントについて書きたいと思います。
※すみません、未完成なのでタイトル詐欺になってしまっています。
※100番煎じなので非同期の書き方に関してはあんまり詳しく書きません。
※arrow関数使ってません。説明省くので。
※間違いあれば教えていただければと思います。
目次
- Node.jsの非同期処理について
- 非同期処理の書き方
2.1 コールバック(callback)関数
2.2 Promise ←この記事はココまで!
2.3 asycn/await
3. Promiseとasycn/awaitが一緒だと思ったらハマった件 - 参考
Nodeを使ったことがあって1~2についてわかってるよって方は3まで飛ばしてください。
1.Node.jsの非同期処理について
Nodeは非同期を多用するという特徴がある。
非同期処理とは
よそに処理を依頼したときに、その場で完了を待たない
処理のことらしい。
ここでは詳しい説明は割愛するが、Nodeは単一のスレッドしか持たないため(シングルスレッドアーキテクチャ)、いちいち同期処理をしていては他の処理の実行を妨げてしまう。
例)同期処理の場合
//受け取った数字を出力する(同期)
function printNumSync(num) {
console.log(num)
}
printNumSync(1)
printNumSync(2)
printNumSync(3)
結果
1
2
3
同期処理の場合は呼び出した順番通りに処理が実行されます。
→前の処理の完了を待ってから次の処理に進む。
・非同期処理の場合
次に同期、非同期、同期処理の順に呼び出してみます。
//受け取った数字を出力する(同期)
function printNumSync(num) {
console.log(num)
}
//受け取った数字を1秒後に出力する(非同期)
function printNumAsync(num) {
setTimeout(function () {
console.log(num)
}, 1000);
}
printNumSync(1)
printNumAsync(2)
printNumSync(3)
結果
1
3
2
先に述べたように非同期処理(例の場合はsetTimeout
が非同期)は、完了を待たずに次の処理へ進むため1の出力後、2つ目の処理の完了前に3が表示されます。
2.非同期処理の書き方
非同期処理にもいくつか書き方があります。
2.1.コールバック関数
「コールバック関数」とはわかりやすく言えば 終わったらコレやっといて
のコレに当たる部分。全然わかりやすくないですね。はい。
非同期処理には処理の完了を待たないという性質がありました。では非同期処理が終わったら**次に何をすればいいのか。**そんな悩みにこたえるのがコールバック関数。
非同期処理にコールバック関数を渡す1ことで、非同期処理の完了後にコールバック関数が実行される。
実は上の非同期の例でも使われていますがsetTimeout
を見てみましょう。
//1秒後に「callbackの中です」と表示
setTimeout(function () {
console.log('callbackの中です')
}, 1000);
//↓↓わかりやすくするとこうなる
//callbackFuncに関数を格納
var callbackFunc = function () {
console.log('callbackの中です')
}
//「setTimeout」が終わったら「callbackFunc」をやっといて
//→ ≒「1秒待つ」が終わったら「callbackFunc」をやっといて
setTimeout(callbackFunc, 1000);
2.2.Promise
以下Node.jsデザインパターンより引用
プロミスは簡単に言えば、「非同期処理の結果を表現するオブジェクト」です。~中略~
プロミスは完了される(fulfilled、成功)か棄却される(rejected、失敗)のいずれかで、このいずれかが起きることは保証されます。完了されてから後で棄却されたり、複数の結果が起きることはありません。
ようは非同期処理が成功したか、失敗したかを扱うオブジェクト。
例)使い方
var fs = require('fs').promises;//ライブラリ読み込み
//1.ファイル読み込み(Promiseを返却する)
fs.readFile('./work.txt')
.then(function (content) {//2.ファイル読み込みが完了したら実行される
console.log(content.toString())
})
.catch(function (error){//2.ファイル読み込みが失敗したら実行される
console.log(error)
});
時間になってしまったので続きは後日書きます。
4.参考
Node.js 非同期処理・超入門 -- Promiseとasync/await
Node.jsデザインパターン
-
Node(というかECMAScript)では関数はオブジェクトとみなされるため、変数に入れることができます。 ↩