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

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

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

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

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

1回答

878閲覧

Node.js GETパラメータをMySQLで検索したいが非同期処理なので思ったように動きません

Clover

総合スコア13

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

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

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2017/11/16 17:11

編集2017/11/16 17:14

http://localhost:3000/home?id=test
GETパラメータのidよりtestを取得し、MySQLのusersテーブルへ接続しカラムidにtestがあった場合はhomeへ、なかった場合はerrorへ。

上記を想定していたのですが、MySQLのconnection.query処理が非同期でreturnされる前に次の処理へ進んでしまい、GETパラメータ(id)による処理の分別(home||errorを表示)が出来ません。

async/awaitなど色々調べたのですが良く分かりませんでした。
どのようにコードを書くのが適切でしょうか?すいませんが、よろしくお願い致します。

javascript

1var http = require('http'); 2var fs = require('fs'); 3var path = require('path'); 4var mysql = require('mysql'); 5var url = require('url'); 6 7// サーバー 8var mime = { 9 ".html": "text/html", 10 ".css": "text/css" 11}; 12var server = new http.createServer(function(req, res) { 13 if (req.url.indexOf('home') !== -1) { 14 var url_parts = url.parse(req.url, true); 15 if (url_parts.query.id !== undefined) { 16 17 if (auth(url_parts.query.id)) { 18 filePath = '/home.html'; 19 } else { 20 filePath = '/error.html'; 21 } 22 } 23 } else { 24 filePath = req.url; 25 } 26 var fullPath = __dirname + filePath; 27 28 res.writeHead(200, {"Content-Type": mime[path.extname(fullPath)] || "text/plain"}); 29 fs.readFile(fullPath, function(err, data) { 30 if (!err) { 31 res.end(data, 'UTF-8'); 32 } else { 33 res.end("Not Found", 'UTF-8'); 34 } 35 }); 36}).listen(3000); 37 38// データベース 39function auth(id) { 40 try { 41 var connection = mysql.createConnection({ 42 host : 'host', 43 user : 'user', 44 password : 'password', 45 database : 'database' 46 }); 47 connection.connect(); 48 49 connection.query({ 50 sql: 'SELECT * FROM `users` WHERE `id` = ?', 51 timeout: 5000, 52 values: id 53 }, function (error, results, fields) { 54 if (results == '') { 55 console.log('存在しないユーザーです。'); 56 return false; 57 } else { 58 console.log('存在するユーザーです。'); 59 } 60 }); 61 connection.end(); 62 return true; 63 } catch (err) { } 64}

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

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

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

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

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

guest

回答1

0

ベストアンサー

動くコードになるか不安ですが単純にasync-awaitに対応させてみます
asnc-awaitは内部的にpromiseを使っているのでpromiseから学習してみるのがいいと思います。

おすすめは以下のドキュメントです
JavaScript Promiseの本

javascript

1 2var http = require('http'); 3var fs = require('fs'); 4var path = require('path'); 5var mysql = require('mysql'); 6var url = require('url'); 7 8// サーバー 9var mime = { 10 ".html": "text/html", 11 ".css": "text/css" 12}; 13var server = new http.createServer(async function(req, res) { //変更1 14 if (req.url.indexOf('home') !== -1) { 15 var url_parts = url.parse(req.url, true); 16 if (url_parts.query.id !== undefined) { 17 18 const result = await auth(url_parts.query.id); // 変更2 19 if (result) { 20 filePath = '/home.html'; 21 } else { 22 filePath = '/error.html'; 23 } 24 } 25 } else { 26 filePath = req.url; 27 } 28 var fullPath = __dirname + filePath; 29 30 res.writeHead(200, {"Content-Type": mime[path.extname(fullPath)] || "text/plain"}); 31 fs.readFile(fullPath, function(err, data) { 32 if (!err) { 33 res.end(data, 'UTF-8'); 34 } else { 35 res.end("Not Found", 'UTF-8'); 36 } 37 }); 38}).listen(3000); 39 40// データベース 41async function auth(id) { //変更3 42 return new Promise((resolve, reject) => { // 変更4 43 try { 44 var connection = mysql.createConnection({ 45 host : 'host', 46 user : 'user', 47 password : 'password', 48 database : 'database' 49 }); 50 connection.connect(); 51 52 connection.query({ 53 sql: 'SELECT * FROM `users` WHERE `id` = ?', 54 timeout: 5000, 55 values: id 56 }, function (error, results, fields) { 57 if (results == '') { 58 console.log('存在しないユーザーです。'); 59 resolve(false); //変更5 60 } else { 61 console.log('存在するユーザーです。'); 62 connection.end(); 63 resolve(true); //変更6 64 } 65 }); 66 } catch (err) { 67 reject(err); //変更7 68 } 69 }); 70} 71

投稿2017/11/17 02:33

編集2017/11/17 02:56
m0a

総合スコア708

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

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

Clover

2017/11/17 02:50

ご回答頂きありがとうございます。 promise、今週中に本格的に勉強を始めてみます。 すいません、コードを動作せてみたのですが、正しく動作しませんでした。 const result = await auth(url_parts.query.id); の関数が実行される前に、resolve(true); が強制的に実行されるようで、resultが必ずtrueになってしまいますOrz
Clover

2017/11/17 02:53

すいません! connection.end(); を function (error, results, fields) { } に含めましたら、問題なく動作しました。 ありがとうございました!
m0a

2017/11/17 02:59

自己解決したみたいでよかったです。基本的にasync-awaitによって関数のネスト呼び出しは撲滅できるので本来はこのコードは理想的ではないです。実際このようにバグが発見されてますし。 ですので理解した上で再修正することをオススメします
Clover

2017/11/17 03:08

ありがとうございます。 何度も質問をすいません。 やはりこのコードですと、 ネストが深くなる、というものでしょうか? それとも、想定しないバグが発生する可能性が高いという事でしょうか?
m0a

2017/11/17 03:14

例えば http.createServerに渡している無名関数 `` async function(req, res) `` は非同期処理を同期的に扱えるのに、まだ非同期関数を含めています。 (``fs.readFile(fullPath, function(err, data) `` の箇所。 ) この箇所も同じようにasync awaitを使って同期的な書き方に直すべきだと思います。
Clover

2017/11/18 04:34

すいません、返信が遅れました。 なるほどです!ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問