はじめに
意外と検索してパパっと出てこないので記事化してみました。
Azure上のMySQLとの接続処理をコーディングしていたので、サンプルのコードはMySQLのusersテーブルからデータを取得する処理をイメージしています。
実現したいこと
async/awaitを使って非同期処理内で関数を同期実行して、返り値を同期的に取得したいケースがあるんじゃないかと思います。
sample.js
(async function() {
response = await requestApi();
console.log(response);
})();
Promiseを返してくれる関数だったら楽でいいのですが、例えば下記のようにコールバックにコールバックを重ねている関数を全て同期処理させた後、値を取得するにはどうすればいいのでしょうか。
dbaccess.js
import * as mysql from 'mysql';
import * as fs from 'fs';
import * as dotenv from 'dotenv';
const config = {
host: process.env.HOST_NAME,
user: process.env.DATABASE_USER_NAME,
password: process.env.DATABASE_USER_PASSWORD,
database: process.env.DATABASE_NAME,
port: 3306,
};
//DBの接続情報設定
const conn = mysql.createConnection(config);
//DBのコネクション処理
conn.connect(function (err) {
if (err) throw err;
//SQLの設定、データ取得
conn.query('SELECT * FROM users', function (err, results) {
if (err) throw err;
//[!]このresultsがほしいケース
console.log(results);
});
//DBのコネクション切断
conn.end(function (err) {
if (err) throw err;
});
});
解決策
Promiseを返してくれる関数を用意してあげて、コールバックの関数を書いていく、そして関数の一番最後でresolveを呼んであげます。
サンプルコードは下記の通りです。
dbaccess.js
~~~~前半は省略~~~~
//DBの接続情報設定
const conn = mysql.createConnection(config);
const fetchUsers = () => {
return new Promise((resolve) => {
//DBのコネクション処理
conn.connect(function (err) {
if (err) throw err;
//SQLの設定、データ取得
conn.query('SELECT * FROM users', function (err, results) {
if (err) throw err;
resolve(results);
});
//DBのコネクション切断
conn.end(function (err) {
if (err) throw err;
});
});
});
};
const users = await fetchUsers();
console.log(users);
参考
コールバック関数の同期実行と非同期実行
teratail コールバック関数から値を返したい
クイック スタート: Node.js を使って Azure Database for MySQL フレキシブル サーバーに接続してデータのクエリを実行する