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

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

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

EJSは、JavaScript用のテンプレートエンジン。HTMLなどのテンプレートテキストにJavaScriptのロジックを記述することができます。また、変数・関数の実行をテンプレートテキスト内に埋め込むことも可能です。

Node.js

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Express

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

Q&A

解決済

1回答

1256閲覧

Node.js,Express, Jacascript, ejs, postgresを使って、データベースのテーブル一覧をページに表示させたい。

224_lei

総合スコア1

EJS

EJSは、JavaScript用のテンプレートエンジン。HTMLなどのテンプレートテキストにJavaScriptのロジックを記述することができます。また、変数・関数の実行をテンプレートテキスト内に埋め込むことも可能です。

Node.js

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Express

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

0グッド

0クリップ

投稿2020/08/06 03:14

編集2020/08/06 03:19

前提・実現したいこと

Node.js,Express, Jacascript, ejs, postgresを使って、データベースのテーブル一覧をページに表示させたいが、エラーが出てしまいます。
データベースにはテーブルが作成してあり、データも入っております。エラー内容はforEach が関数として認められないという内容です。
サーバを起動すると、successと表示されるため、DBとの接続は成功しているようです。
初心者のためまったくの基本的なミスかもしれませんが、ご教示いただけると嬉しいです。

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

items.forEach is not a function

22| </div> 23| <ul class="table-body"> >> 24| <% items.forEach((item) => { %> 25| <li> 26| <div class="item-data"> 27| <span class="id-column"><%= item.id %></span> items.forEach is not a function

該当のソースコード

>main.js const express = require('express'); const ejs = require('ejs'); const app = express(); app.set("view engine", "ejs") const { Client } = require('pg') const client = new Client({ //接続情報 }); client.connect((err) => { if (err) { console.log('error connecting: ' + err.stack); return; } console.log('success'); }); app.get('/', (req, res) => { client.query( 'SELECT * FROM items', (error, results) => { res.render('index.ejs', {items:results}); } ); }); app.listen(3000); >ここからindex.ejs <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LIST APP</title> <script src="/send_url.js"></script> </head> <body> <header> <a class="header-logo">LIST APP</a> </header> <div class="container"> <div class="container-header"> <h1>買い物リスト</h1> <a href="/new" class="new-button">+ 新規登録</a> </div> <div class="index-table-wrapper"> <div class="table-head"> <span class="id-column">ID</span> <span>買うもの</span> </div> <ul class="table-body"> <% items.forEach((item) => { %> <li> <div class="item-data"> <span class="id-column"><%= item.id %></span> <span class="name-column"><%= item.task %></span> </div> </li> <% }) %> </div> </ul> </div> </div> </body> </html>

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

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

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

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

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

guest

回答1

0

ベストアンサー

ejsのitems.forEach(fn)に着目してください。

JavaScriptに於いて
値のお尻にある括弧()は関数呼び出しを意味します。
これは値が関数である事が絶対で、関数でなければエラーで落ちます。

試しに数値に対して()を付けてみましょう。

> num = 123 > num() Uncaught TypeError: num is not a function > out = function(){ return 123 } > out() 123

質問文と同じエラーになりましたね。
とりあえずitems.forEachは関数ではない事がわかりました。


JavaScriptに於いて、
変数名などの途中に.があるのはプロパティを意味します。

items.forEachitemsforEachというプロパティを所持しているはず
じゃあこのforEachプロパティは何者やねん。
誰が決めてるの?

これは途中のコードが端折られているため正確なところは分かりませんが、
恐らくは配列のメソッドを指しているのでしょう。
Array.prototype.forEach

JavaScriptはオブジェクト指向言語ですので、
null等の例外を除き、値として存在できるものは全てプロパティを所持しています。
所持しているプロパティが関数ならばメソッドと呼びます。

そしてJavaScriptは配列ならばmapforEach等のプロパティを所持しているという決まりがあります。
試しに確認してみましょう。

> [1, 2, 3].forEach ƒ forEach() { [native code] }

配列はforEachメソッドを所有している事が確認できました。
つまりitemsforEachメソッドを所持していない。
要するにこいつは配列じゃないとわかります。

ejs内のitemsって何処から来たんですっけ?
res.render('index.ejs', {items:results});で表現されていますね。
resultsが配列じゃないから、受け取ったitemsも配列じゃないのです。


このresultsがどこから来たのかも追ってみましょう。
const { Client } = require('pg')というコードがあり、
npmモジュールのnode-postgresを利用している事がわかります。
pg - npm

その中の⭐️ Documentation ⭐️からドキュメントへ飛び
queryで使い方を見てみましょう。

js

1client.query('SELECT $1::text as message', ['Hello world!'], (err, res) => { 2 console.log(err ? err.stack : res.rows[0].message) // Hello World! 3 client.end() 4})

これのコールバック関数の第2引数で、
res.rows.0という風にたどっている事がわかります。

res汎用オブジェクト
res.rowsは添字でのプロパティ呼び出ししているので恐らく配列なんでしょうね。

質問文のコードに戻って考えると、
resutsは汎用オブジェクトなので、forEachメソッドは所持していないはずです。
ここが誤り。

結果を意味するrowsプロパティにすれば良いんじゃないですかね?
items: results.rowsに変更すれば少しは進むと思います。

余談ですが、結果は複数形ではないですね。
DB問い合わせという1個の結果のrowsという結果一覧表が配列、つまり複数形です。
resultという風に単数形の引数名に変更したほうが良いでしょうね。

投稿2020/08/06 04:44

編集2020/08/06 04:51
miyabi-sun

総合スコア21158

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

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

224_lei

2020/08/07 02:40

ありがとうございました。rowsを追加したことによって進められました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問