質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1754閲覧

コールバック関数内から値を返す方法

kawauso

総合スコア56

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/08/12 05:09

編集2020/08/12 07:21

前提・実現したいこと

Node.js + MySQLで開発を行ています。
DBに特定のIDが登録されているかどうかの値(bool型)を返す関数を作成したいと思っております。
(Node.js(JavaScript)での開発はこれが初めてとなります。)

発生している問題・エラーメッセージ

下記のコードでtrueになるような引数を与えてもfalseしか返ってきません。

該当のソースコード

修正1

javascript

1var http = require('http'); 2const mysql = require('mysql'); 3const connection = mysql.createConnection({ 4 host: '', 5 user: 'aaa', 6 password: 'bbb', 7 port: '3306' 8}); 9 10async function isRegistered(id) { 11 var result = false; 12 13 var query = `SELECT EXISTS (SELECT * FROM hoges WHERE id = '${id}') as result;`; 14 await connection.query(query, (err, rows, fields) => { 15 result = Boolean(rows[0].result); // ★3番目に呼ばれる 16 }); 17 18 return result; // ★1番目に呼ばれる 19} 20 21// 呼び出し元 22http.createServer(async function (req, res) { 23 if (req.method == 'POST') { 24 var result = awit isRegistered('hogehoge'); 25 console.log(result.resolve);// ★2番目に呼ばれる 26 } 27}).listen(8080);

試したこと

Node.jsの経験が浅いので断定できませんが、
非同期処理のため想定している値と別の値が返ってきてしまうのだと考えています。
(err, rows, fields) => {}の前にasyncなどを付けて試してみましたが、解決には至りませんでした。
解決策をご存知であれば、ご教授よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

VisualStudio 2019
Node.js v12.18.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

素のmysqlパッケージはPromiseを使えないようなのでコールバックで延々繋いでいくしかないと思います。Promiseを使えればawaitも使えると思うので良かったら、

https://www.npmjs.com/package/promise-mysql

あたりを試してみるのもいいかもしれません。(試してません)

javascript

1const mysql = require('mysql'); 2const connection = mysql.createConnection({ 3 host: '', 4 user: 'aaa', 5 password: 'bbb', 6 port: '3306' 7}); 8 9function isRegistered(id, resolve) { 10 var result = false; 11 12 var query = `SELECT EXISTS (SELECT * FROM hoges WHERE id = '${id}') as result;`; 13 connection.query(query, (err, rows, fields) => { 14 result = Boolean(rows[0].result); 15 resolve(result); 16 }); 17} 18 19isRegistered('hogehoge', (result)=>{ 20 console.log(result); 21});

一応promise-mysqlのサンプルも書いときました。

javascript

1const mysql = require('promise-mysql'); 2 3(async () => { 4 const connection = await mysql.createConnection({ 5 host: 'localhost', 6 user: 'homestead', 7 database: 'homestead', 8 password: 'secret', 9 port: '13306' 10 }); 11 12 const rows = await connection.query(`SELECT * FROM item;`); 13 console.log(rows); 14 connection.end(); 15})();

最後に上のサンプルをmysqlを使って自前のPromiseで処理するとすると...

javascript

1const mysql = require('mysql'); 2 3async function mysql_createConnection(option) { 4 return Promise.resolve(mysql.createConnection(option)); 5} 6 7async function connection_query(connection, query) { 8 return new Promise((resolve, reject) => { 9 connection.query(query, (error, results, fields) => { 10 if (error) { 11 reject(error); 12 } else { 13 resolve(results); 14 } 15 }); 16 }) 17} 18 19(async () => { 20 const connection = await mysql_createConnection({ 21 host: 'localhost', 22 user: 'homestead', 23 database: 'homestead', 24 password: 'secret', 25 port: '13306' 26 }); 27 28 const rows = await connection_query(connection, `SELECT * FROM item;`); 29 console.log(rows); 30 connection.end(); 31})();

投稿2020/08/12 21:17

編集2020/08/12 22:23
dameo

総合スコア943

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kawauso

2020/08/12 23:10

ご回答ありがとうございます。 promise-mysqlはまだ試せていませんが、その他2点の方法で動作が確認できました。 助かりました。ありがとうございました!
guest

0

async await は、普通は、こういう風に付けるかと思いますが、

js

1async function isRegistered(id) { 2: 3 await connection.query(query, (err, rows, fields) => { 4 result = Boolean(rows[0].result); 5 });

mysql.createConnection
の動作がわからないので、なんともです。

戻り値、ではなくて、グローバル的な値をコールバック側で書き換えたほうがわかりやすいかもしれないです。

非同期処理はややこしいもんです。

投稿2020/08/12 05:52

standard-soft

総合スコア197

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kawauso

2020/08/12 06:36

ご回答ありがとうございます。 mysqlに関する記述、関数呼び出し元を追記しました。 (質問文 修正1)async/awaitを回答のように付け加えてみました。そうすると次はtrueしか返ってこなくなりました。デバッグで追いかけましたが、isRegisteredのresultにはきちんとfalseが代入されていましたが、なぜか呼び出し元ではtrueが返ってきてしまいます。 (質問文 修正2)グローバル変数で試してみましたが、今度はresultがundefinedのままでした。
kawauso

2020/08/12 06:52

申し訳ございません。修正1ですが.resolveをつけていませんでした。 result.resolveの結果はundefinedとなってしまいます。 デバッグしているとisRegisteredのreturn resultまでいかないのですが、何か原因をご存知でしょうか。
standard-soft

2020/08/12 06:54 編集

``` http.createServer(async function (req, res) { if (req.method == 'POST') { var result = await isRegistered('hogehoge'); console.log(result); } }).listen(8080); ``` 追加部分のところ、こうではないかと思うのです。 実行環境が用意できないので、あてずっぽうで申し訳ないところですが。
kawauso

2020/08/12 07:09

ご回答ありがとうございます。 ご回答のように試してみましたが、実行と同時にプログラムが終了してしまいます。 エラー文等も出力されませんでした。
kawauso

2020/08/12 07:25

何度も申し訳ございません。落ちるのはこちらのミスでした。 質問文のコードの★印のところにブレークポイントを打って検証してみるとコールバック内の値が最後に呼び出されていることが分かりました。 なので、デフォルト値として代入しているfalseが返ってきしまっているようです。
standard-soft

2020/08/12 08:27

connection.query が、async関数ではないようですね。 connection.query( に渡しているコールバック関数で行いたいことを実装するしか、 ないような気がします。 mysql.createConnection などのサンプルに非同期処理のところで、何かサンプルを検索して真似してみるとかでしょうか。 このくらいのことしかわかりませんでした。 すいません、大してお力になれずです。
kawauso

2020/08/12 08:54

回答ありがとうございます。 いろいろ調べてみたいと思います。解決できれば追記します。 お付き合い頂きありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問