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

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

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

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

JavaScript

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Q&A

解決済

1回答

6709閲覧

connection.query の実行結果を返す関数を作りたい。

ws156

総合スコア1

Node.js

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

JavaScript

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

0グッド

0クリップ

投稿2020/11/15 10:01

実現したいこと

JavaScript

1console.log( 2 m_sql( 3 "SELECT * FROM accounts WHERE user=?;", ["Jhon"] 4 ).results[0].mail_address 5);

みたいな感じに、Node.jsでSQL文をm_sql()関数に渡し、SQL文の実行結果をm_sql()関数の戻り値として受け取る。
このm_sql()関数を作りたい。

つまずいてる場所

JavaScript

1const mysql = require("mysql"); 2 3const connection = mysql.createConnection({ 4 host: "localhost", 5 user: "root", 6 password: "toor", 7 database: "test" 8}); 9 10/*=============================================================*/ 11 12function m_sql (code, argv) { 13 var ret; 14 15 new Promise((resolve, reject) => { 16 // connection.query は非同期関数なので、Promise を使っています。 17 connection.query(code, argv, 18 (error, results, fields) => { 19 resolve({ 20 error: error, 21 results: results, 22 fields: fields 23 }); 24 } 25 ); 26 27 }).then(data => { 28 ret = data; 29 30 console.log(data); 31 //=> SQL文の実行結果 32 33 console.log(ret); 34 //=> SQL文の実行結果 35 36 //ここでは無事、retにSQL文の実行結果が入っていますが、 37 }); 38 //ここではretがundefinedになっています 39 40 console.log(ret); 41 //=> undefined 42 43 return ret; 44} 45 46console.log(m_sql("SELECT * FROM auth;")); 47//=> undefined

知りたいこと

  • どうやったら、retが SQL文の実行結果を保持したまま、return出来るのか。

調べたこと・試したこと

  • 参照渡し

JavaScript の参照渡しはややこしいし、やってもできなかった。
参照渡しは存在しないという記事も。

環境・バージョン

  • OS Windows 10 Home 64bit
  • Node.js v12.16.1
  • SQL 10.5.5-MariaDB

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

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

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

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

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

guest

回答1

0

ベストアンサー

Promiseの動作について誤解が発生していると思います。retに発生している問題は「保持できていない」ではなく「代入していない」です。直感的ではないかもしれませんが、このコードは次の順番で処理が行われています:

javascript

1 function m_sql (code, argv) { 2/* 1 */ var ret; // 未代入 3 4 new Promise((resolve, reject) => { 5/* 3 */ connection.query(code, argv, 6/* 4 */ (error, results, fields) => { 7/* 5 */ resolve({ 8 error: error, 9 results: results, 10 fields: fields 11 }); 12 } 13 ); 14 }).then(data => { 15/* 6 */ ret = data; // ここで代入される 16 }); 17 18 // 「`Promise`を待て」と言われていないため、ここまで飛ばされてしまう 19 20/* 2 */ return ret ; // 未代入 21 } 22 23 console.log(m_sql("SELECT * FROM auth;")); // 2のステップで出力される

これを解決するためにm_sql()自体を非同期化(Promise化)してしまいましょう。

javascript

1// 頭に`async`を付けることで、関数の返り値を`Promise`にします 2async function m_sql (code, argv) { 3 // `var ret`は不要 4 5 // `new Promise`の前に`await`を付けることで、`Promise`の解決を待つ 6 const data = await new Promise((resolve, reject) => { 7 connection.query(code, argv, 8 (error, results, fields) => { 9 resolve({ 10 error: error, 11 results: results, 12 fields: fields 13 }); 14 } 15 ); 16 17 // ここに到達した時点で`Promise`の処理の完了が保障されている 18 19 // `.then(...)`は不要 20 21 return data; // `data`を直接返すことができる 22}

この関数(非同期関数)を呼び出すときは頭にawaitを付けてPromiseの解決を待ちましょう:

javascript

1// 関数の外で`await`を使うことを「Top-level await」と呼びます 2console.log(await m_sql("SELECT * FROM auth;"));

古いnodeのバージョン(14.7.0以前)ではTop-level awaitがサポートされていないため、全体をasync main関数で囲む必要があります:

javascript

1async function main () { 2 // 処理全体をここに入れてください 3 console.log(await m_sql("SELECT * FROM auth;")); 4} 5 6main();

投稿2020/11/15 13:44

編集2020/11/15 13:48
itepechi

総合スコア248

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

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

ws156

2020/11/16 09:12

無事解決できました。 なるほど!Promise と async/await にそんな関係があったんですね! あと、実行順序も結構衝撃的でした。 Node.jsに新しいバージョンが出たことも初めて知りました。 早速アップデートしました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問