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

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

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

MongoDBはオープンソースのドキュメント指向データベースの1つです。高性能で、多くのリトルエンディアンシステムを利用することができます。

JavaScript

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

Q&A

解決済

2回答

2951閲覧

Javascriptの配列をグローバル変数にpushできない

Mikamikachan

総合スコア2

MongoDB

MongoDBはオープンソースのドキュメント指向データベースの1つです。高性能で、多くのリトルエンディアンシステムを利用することができます。

JavaScript

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

0グッド

1クリップ

投稿2021/10/26 16:03

編集2021/10/26 16:18

履修登録システムを作る課題をしております。
mongooseにある生徒情報をfind()を使って全て取り出しpushでグローバル変数に入れたいのですが、
実行後、そのグローバル変数の中身が[]と表示されます。
ローカル変数にpushした場合は上手くいくのですが、なぜグローバル変数にはpushされないのかがわからないため、
こちらで質問させていただきました。

var data = []; Students.find() .exec() .then((students)=>{ for(const student of students){ data.push({ number: student.number, firstName: student.firstName, lastName: student.lastName, id: student._id }) } }) console.log(data); // []

説明不足や至らない点があるかと思いますが、ご教示いただけると幸いです。

追記
forループの直前にconsol.log(students)を置くと、中身がきちんと表示されているので、この時点でデータは取り出しができているのがわかります。それと以下のようにグローバル関数ではなくローカル関数にして置き換えてみるときちんとデータがpushされます。

Students.find() .exec() .then((students)=>{   var data = []; for(const student of students){ data.push({ number: student.number, firstName: student.firstName, lastName: student.lastName, id: student._id }) } console.log(data); // データが表示される })

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

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

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

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

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

guest

回答2

0

ベストアンサー

Students.find().exec().then(() => {...})となっているところは非同期な処理ですね。
thenの中に書いている処理(関数)はすぐに実行されるのではなく、exec()の処理が正常に完了した時、
つまりMongooseからの結果を受け取った時に実行されます。

よって、console.log(data)が実行されるタイミングではまだ何も入っていない空の配列となります。
下記のように、実際にどんな処理順で実行されているか確認してみるとわかりやすいかもしれません。

javascript

1var data = []; 2console.log('log1') 3Students.find() 4.exec() 5.then((students)=>{ 6 console.log('log2') 7 for(const student of students){ 8 data.push({ 9 number: student.number, 10 firstName: student.firstName, 11 lastName: student.lastName, 12 id: student._id 13 }) 14 } 15}) 16console.log('log3') 17 18console.log(data); // []

thenの中の処理は後から(MongoDBからデータを取得したタイミング)で実行されるので、
上記のconsole.logで出力しているテキストが標準出力される順番は

log1 log3 [] log2

となります。

非同期はJavascriptではかなり重要な機能なので是非勉強してみてください。
Javascript 非同期 しくみとかJavascript Promiseとかでググると
解説の記事がいっぱい出てくると思います。

(説明したいんですけど語彙力が低いので簡潔に説明できそうにないです・・・。)

投稿2021/10/26 16:20

ukyoda

総合スコア386

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

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

Mikamikachan

2021/10/29 17:34

ukyodaさん、お返事ありがとうございます。 javascriptを勉強するうえで非同期、同期の概念が重要なことがわかりました。 今回はasync awaitを使用しコードを書き直してみたところ、data内のデータをconsole.logで表示することがきました(この方法があっているのかは正直自信はありませんが。。。) 丁寧にわかりやすく回答していただきありがとうございました!
guest

0

async awaitを使用しコードを書き直してみたところグローバル変数data内に生徒情報がpushされconsole.logで表示することができました。
どういうタイミングで処理を非同期、同期にする必要があるのか、まだ完全には理解できてはいないので、これから非同期、同期についてもう少し学ぼうと思います。

今回はありがとうございました!

var data = []; console.log("log1"); async function getAllStudents(){ await Students.find() .exec() .then((students)=>{ console.log('log2'); for(const student of students){ data.push({ number: student.number, firstName: student.firstName, lastName: student.lastName, id: student._id }) } }) } getAllStudent() .then(result=>{ console.log("log3"); console.log(data); }) .catch((err)=>{ console.log(err); }) ///log1 ///log2 ///log3 ///生徒情報

投稿2021/10/29 17:47

Mikamikachan

総合スコア2

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問