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

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

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

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

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

Q&A

解決済

2回答

7130閲覧

Node.js(express)で関数の途中で処理を終わらせる方法がわからない

twipg

総合スコア30

Node.js

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

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

0グッド

1クリップ

投稿2015/06/11 23:14

ユーザーIDをGetパラメータで受け取り、DBのテーブルを検索後、一致していれば後続の処理を行い、一致しなければ処理を中断させるという関数を作っております。

具体的にはrouter.getの最初の行でidCheck関数を呼び、idがDBのテーブルに一致すればtrue、一致しなければfalseを返します。

その後、returnでrouter.getに戻り、

if(!idCheck(req, res)) return;

という文でidの一致、不一致を判定しようと思ったのですが、どちらもif文に引っかかり、returnとなり、一致した場合でも後続の処理に入れません。

どのような書き方をすればtrueとfalseのif文を上手く動かすことが出来るのでしょうか?

よろしくお願いします。

/* Function test */
function idCheck(req, res) {
User.find({ userid : req.params.id }, function(err, items){
if (err) {
console.log(err);
res.writeHead(401, {
'Content-Type': 'text/plain'
});
res.end('failed.');
return false;
} else {
if (items.length === 0) {
console.log('failed. Not registered!');
res.writeHead(401, {
'Content-Type': 'text/plain'
});
res.end('failed. Not registered!');
return false;
} else {
console.log('successed!!');
return true;
}
}
});
}

/* GET users */
router.get('/api/users/:id', function(req, res) {
if(!idCheck(req, res)) return;
// 以下、処理
});

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

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

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

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

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

guest

回答2

0

ベストアンサー

次のようなコードを手元で動かしてみてください。

lang

1function idCheck(req, res) { 2 User.find({ userid: req.params.id }, function(err, items){ 3 console.log("Userテーブルの検索が終了しました"); 4 }); 5} 6 7if (!idCheck(req, res)) { 8 console.log("idCheck関数の処理が終了しました"); 9}

コマンドラインには次のように表示されると思います。

lang

1idCheck関数の処理が終了しました 2Userテーブルの検索が終了しました

これは、idCheck関数がUser.findメソッドにfunction(err, items){...}という関数を登録し終えると、即座に関数を抜けてしまうからです。「登録する」という部分が重要で、登録される関数は、即座に実行されるとは限りません。User.findメソッドはその典型です。登録した関数は、DBのテーブルを検索し終えたあとで実行されます。

このように、非同期な動きをする関数を扱うのは少し厄介です。過去にも沢山の人が困ったらしく、ECMAScript 6から、このような問題の解決手段としてPromiseという仕組みが用意されました。

Promiseは、非同期処理を同期的に扱うための手段の一つとして用意されました。Promiseコンストラクタを使うと、質問者さんのコードは次のように書き換わります。

lang

1function idCheck(req, res) { 2 return new Promise(function(resolve, reject) { 3 User.find({ userid: req.params.id }, function(err, items) { 4 if (err) reject({ errno: 1, message: err }); 5 if (items.length === 0) reject({ errno: 2 }); 6 resolve(); 7 }); 8 }); 9} 10 11router.get('/api/users/:id', function(req, res) { 12 idCheck(req, res).then( 13 function() { 14 /* 成功した時の処理を書く */ 15 }, 16 function(obj) { 17 switch (obj.errno) { 18 case 1: 19 console.log(obj.message); 20 break; 21 case 2: 22 console.log('failed. Not registered!'); 23 break; 24 } 25 }); 26});

(routerオブジェクトが何であるかを把握できなかったので、writeHeadメソッドやendメソッドはないものとして考えました)

質問者さんのコードとの主な違いは、

idCheck関数はPromiseコンストラクタのインスタンスを返す
②DBテーブル検索終了後の処理が.then()メソッドの引数の関数内に書かれている
resolve関数やreject関数などの見慣れない関数がある

などです。最初はこれらの仕様に戸惑うかもしれませんが、理解すると、非同期処理を同期的に書く手段として優れたものの一つだということがわかるかと思います。

各メソッドや関数の意味は、MDNのPromiseのリファレンスなどを参考にしてみてください。

投稿2015/06/12 01:35

編集2015/06/12 01:36
anaprestoo

総合スコア199

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

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

twipg

2015/06/14 04:35

丁寧な回答有難うございます。 とても助かりました。 非同期処理のプログラミングがわかっていなかったので、 非常に勉強になりました。 徐々に非同期処理のプログラミングに慣れていきたいと思います。
guest

0

User.find関数が非同期なのでidCheck関数がUser.find関数の終了前に終わってしまっているのだと思います。
promiseを戻せると思うので、それの成功・失敗で切り分けると良いかなと思います。

投稿2015/06/11 23:28

naga3

総合スコア1293

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

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

twipg

2015/06/14 04:35

回答有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問