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

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

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

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

JavaScript

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

Express

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

Q&A

解決済

1回答

2390閲覧

別ファイルの関数呼び出し

jackfrost

総合スコア19

Node.js

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

JavaScript

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

Express

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

0グッド

0クリップ

投稿2018/06/16 14:08

前提・実現したいこと

node.js初心者です。
local:8080にアクセスがあったら、ソースコードのあるディレクトリ内の.jsか.htmlのファイル一覧を表示する。
という機能を実装したいのですが、node.jsで関数の結果がundifinedになってしまうようです。
原因がわからず困っております。

※タスク
1.カレントディレクトリの末尾が.jsか.htmlのファイルを取得する関数をモジュールとして別ファイルに作成
2.function.js内の関数をmain.jsから引数を渡して実行
3.結果をmain.jsのdataに入れる
4.Vueでテンプレに表示

該当のソースコード

main.js

1const Vue = require('vue') 2const server = require('express')() 3const renderer = require('vue-server-renderer').createRenderer() 4const list = require("./function.js"); 5 6server.get('*', (req, res) => { 7 var test = list("./"); 8 const app = new Vue({ 9 data: { 10 url: req.url, 11 items: test 12 }, 13 template: require('fs').readFileSync('./template.html', 'utf-8') 14}) 15 16 renderer.renderToString(app, (err, html) => { 17 res.send(html) 18 }) 19}); 20server.listen(8080)

function.js

1const fs = require('fs'); 2console.log('module load!'); 3 4//ファイル一覧取得関数 5var readdir = function (dir) { 6 fs.readdir(dir, function (err, files) { 7 if (err) { 8 throw err; 9 } 10 files.filter( function( value ) { 11 //特定の拡張子を含むものだけ抽出 12 return value.match( /.js$|.html$/g ); 13 }) 14 }); 15} 16module.exports = readdir;

試したこと

1.テンプレにはdataの値が入っていれば表示される(ベタ書きでテストしました)
2.function.js自体は動いている(module.exportせずにfunctins.jsだけで実行しテストしました)
3.main.js側のconsole.logで関数の結果がundefinedと表示される。

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

bash-3.2$ node -v v9.5.0

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

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

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

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

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

guest

回答1

0

ベストアンサー

readdir 関数が値を何も返してないですね。
せっかくなのでこのまま非同期にファイル一覧取得できるようにしてみましょう。

javascript

1const util = require('util'); 2const fs = require('fs'); 3 4// fs.readdir を Promise インスタンスを返すようにラッピング 5// Node.js v10 の場合は require('fs').promises.readdir があるのでそちらを使えば良い 6const readdir = util.promisify(fs.readdir); 7 8// 正規表現のパターンを作るときはパースに少し時間かかる処理なので、 9// なるべくループの外側で作るのが良い 10const FILTER_REGEX = /.(js|html)$/; 11 12module.exports = function (dir) { 13 // 読み込んだファイル一覧をフィルタリングして返す 14 return readdir(dir).then(files => files.filter(value => FILTER_REGEX.test(value))); 15};

使うときは、下記のように async/await を使うとネストが一段深くならないで済みます。

javascript

1server.get('*', async (req, res) => { 2 const test = await list("./"); 3 4 const app = new Vue({ 5 data: { 6 url: req.url, 7 items: test 8 }, 9 template: require('fs').readFileSync('./template.html', 'utf-8') 10 }); 11 12 renderer.renderToString(app, (err, html) => { 13 res.send(html); 14 }); 15});

投稿2018/06/16 19:04

yhg

総合スコア2161

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

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

jackfrost

2018/06/17 13:31

yhgさま ご回答ありがとうございます。 教えていただいたコードが動くことは確認できたので、目的は達成できそうなのですが、当方jsとnode.js自体が初心者のためコードの理解に時間がかかりそうです。 特に以下の部分が理解できないため、解説していただけると助かります。 ■質問1 ``` value => FILTER_REGEX.test(value) ``` 上記の部分でフィルタリングしているのだろうと推測できるのですが、なぜtestでフィルタリングできるのか理解できません。なぜbooleanが返らないのか。。。 ■質問2 最初に私が書いたコードのどこに不備があったのか分からないと、また同じ間違いをすると思うので、間違いを指摘して欲しいです。 教えていただいたコードを参考に作り替えたりしてテストしましたが、やはりうまくいきませんでした。 なぜ結果が返らないのか教えていただけるとありがたいです。
yhg

2018/06/17 13:54

■回答1 その部分は普通に boolean 返っていますが、その外側の filter メソッドでフィルタリングしてます。 files => files.filter(value => FILTER_REGEX.test(value)) を ES5 記法で書くと function (files) { return files.filter(function (value) { return FILTER_REGEX.test(value); }); } のようになります。 ■回答2 var readdir = function (dir) { fs.readdir(dir, function (err, files) { if (err) { throw err; } files.filter( function( value ) { //特定の拡張子を含むものだけ抽出 return value.match( /.js$|.html$/g ); }) }); } この部分ですが、一番外側の readdir 関数は何も値を返していませんので、readdir 関数を呼び出しても何も返ってきません。 また、 var readdir = function (dir) { let results; fs.readdir(dir, function (err, files) { if (err) { throw err; } results = files.filter( function( value ) { //特定の拡張子を含むものだけ抽出 return value.match( /.js$|.html$/g ); }); }); return results; } のように変数に入れればいけるだろみたいな発想になってしまう人もいると思いますが、fs.readdir 関数は非同期関数なので、return results; に到達した時点では変数 results に何も入っていないので空の値を返してしまいます。というわけで、今回のように Promise の出番になるわけです。
jackfrost

2018/06/17 14:42 編集

yhgさま 分かりやすい解説をありがとうございます。 同期・非同期はまったく意識していなかったため、大変勉強になりました。 fs.readdirSyncにしたらPromiseと同じ結果が得られました。 ご指摘ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問