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

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

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

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

JavaScript

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

Q&A

解決済

3回答

16016閲覧

[node.js] 関数の戻り値を作成し、変数に格納したい

lirlia

総合スコア49

Node.js

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

JavaScript

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

0グッド

0クリップ

投稿2016/11/05 16:04

###前提・実現したいこと

node.jsを使用しAmazonのDynamoDBに接続して、テーブル内クエリを取得しようとしています。

console.logに出力はできたのですが、これを変数に格納する方法がわかりません。

###該当のソースコード

javascript

1 2function getAllQuery(table_name) { 3 4 var params = { 5 TableName: table_name, 6 Select: "ALL_ATTRIBUTES" 7 }; 8 var result = dynamodb.scan(params, function (err, data) { 9 if (err) { 10 console.log(err); // エラー時 11 } else { 12 console.log(data['Items']); 13 } 14 }); 15}; 16 17getAllQuery(TABLE_ACCOUNT_LIST);

理想としては下記のように、関数の戻り値にクエリを格納したいと思っております。

javascript

1 2var result = getAllQuery(TABLE_ACCOUNT_LIST);

いろいろと調べてはいるのですが、調べ方のとっかかりがなく困っています。
どのように関数を改変すれば良いか教えていただけないでしょうか。

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

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

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

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

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

guest

回答3

0

ベストアンサー

Javascriptでは、外部とのI/Oがある場合、非同期に処理する必要があります。まれに同期的な関数が用意されている場合もありますが、基本的には、コールバック関数によって、「非同期にデータを受け取らなければならない」と思ってください。
従いまして、残念ながら、

javascript

1var result = getAllQuery(TABLE_ACCOUNT_LIST);

のように呼び出すことはできません。livetc様の回答のように

javascript

1getAllQuery(table_name, callback){ 2// 処理 3callback(data['Items']); 4}

というようにサブルーチンを作成し、呼び出し側も

javascript

1getAllQuery(TABLE_ACCOUNT_LIST, function (result) { 2 // result 受け取り後の処理 3});

と書くようにする必要があります。これがコールバック地獄と呼ばれており、この function のネストが深くなりすぎないようにする技がいろいろとありますので、「Javascript コールバック地獄」などで検索してみてください。

参考:Node.jsのコールバック地獄をPromiseやGeneratorを使って解消する

###コールバックによる非同期動作について
他の回答へのコメントを見ていて、コールバックによる非同期動作について解説する必要があるかと思い、追記します。

もとのコードのdynamodb.scan を呼び出した時、この API はその終了を待たずに帰ってきます。
すると、getAllQueryの実行自身も終了し、 function (err, data) {}で記述した内容は実行を保留された状態になります。この保留された内容はプログラム全体が終了まで実行されません。したがいまして、

javascript

1var result = getAllQuery(TABLE_ACCOUNT_LIST); 2// result を参照する処理

と書きたくても、 result に結果を入れることは不可能なのです。一旦、プログラムを終了すれば、保留されていたコールバック(function (err, data) {}で記述した内容)が実行されます。そして、そこから新たな旅を始めなければなりません。

node.js はシングルスレッドで動作しており、
0. 読み込んだプログラムの実行
0. 保留されたコールバックのうち、実行可能なもの(I/Oが終わったもの)を一つ選び実行
0. 2.を繰り返し、保留されたコールバックがなくなるとプロセスを終了

という処理を行います。シングルスレッドであるため、I/O ごとにスレッドの実行を保留することは性能上許されません。そのかわりにマルチスレッドプログラミングのように微妙なタイミングを考えてmutex を使ったりする必要が無いわけです。

投稿2016/11/06 01:23

編集2016/11/06 02:00
mit0223

総合スコア3401

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

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

lirlia

2016/11/06 13:43

ご丁寧なご回答ありがとうございました。 コールバックの仕様的にどうやるのだろう?と思っていたのですが、「不可能」と断定いただきすっきりしました。
guest

0

getAllQuery(table_name, callback){
// 処理
callback(data['Items']);
}
とかですかね。

投稿2016/11/06 01:01

livetc

総合スコア86

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

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

lirlia

2016/11/06 01:20

いただきましたご指摘をコードに反映しました。 ``` function getAllQuery(table_name, callback) { var params = { TableName: table_name, Select: "ALL_ATTRIBUTES" }; dynamodb.scan(params, function (err, data) { if (err) { console.log(err); // エラー時 } else { callback(data['Items']);  ← callbackに変更 } }); }; ``` console.logでの呼び出し方はわかるのですが、変数に格納する方法は相変わらずわからないため、こちらも方法を教えていただけないでしょうか。 ``` getAllQuery(TABLE_ACCOUNT_LIST, function(data){ console.log(data); })); ```
guest

0

returnしても取得できないのですか?

http://www.ajaxtower.jp/js/function/index4.html

投稿2016/11/06 00:45

hiim

総合スコア1689

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

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

lirlia

2016/11/06 00:53 編集

ご回答ありがとうございます。 実は、returnもためしてみたのですが値が帰ってきません。 コールバック関数内に仕込んだreturn結果の受け取り方がわからず困っています。 function getAllQuery(table_name) { var params = { TableName: table_name, Select: "ALL_ATTRIBUTES" }; var result = dynamodb.scan(params, function (err, data) { if (err) { console.log(err); // エラー時 } else { //console.log(data['Items']); return data['items']; } }); };
hiim

2016/11/06 01:32

すいません、コードよく見てませんでした
hiim

2016/11/06 02:23

コード軽く読み飛ばして普通の関数(同期)かのように勘違いしてました、非同期に関する回答別の方が素晴らしい回答されてますのでそちらを参考にしてください。 非同期は、 「この仕事(※1)やっといてよ、俺は自分の仕事あるからそっちやっとくから(※2)、終わったら結果を喫煙所(※3)で教えてね」 という感じの処理で 今回のばあい (※1)DBのscan (※2)dynamodb.scanの下の処理(関数終了する) (※3)callbackという場所してい なのでgetAllQueryが終了した時にはまだscanの結果は存在しないという事です。 非同期の考え方は http://qiita.com/YoshikiNakamura/items/732ded26c85a7f771a27 の「非同期処理を行なう関数を作る(コールバック版)」あたり参考にされてくださいm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問