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

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

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

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

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

1回答

3477閲覧

callback内で受け取ったデータをグローバル変数に反映する方法に関して

strawberry

総合スコア14

Node.js

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

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2017/09/13 06:18

編集2017/09/13 07:05

javascript(node.js)初心者です。
APIの実行結果をコールバックで受け取り、パースした上で、グローバル変数に反映したいと考えています。

下記スニペットのようなやり方だとだと、コールバック外のobjは、callback時のObject.assignが反映されていません。
callbackを抜けた後で受け取るのは、非同期という特性上難しいのだというのはわかったのですが、
callbackの処理内でグローバル変数 var objを書き換える方法はないのでしょうか?

javascript

1"use strict"; 2var obj = {hoge: "hoge"}; 3 4getAPIData(request,obj, function(result,obj){ 5 //処理内容 6 console.log(obj);//{hoge: "hoge"}; 7 Object.assign(obj,{result: result}) 8 console.log(obj);//{hoge: "hoge", result: "result"} 9}); 10 11console.log(obj);//{hoge:"hoge"} 12 13function getAPIData(request,obj, callback) { 14 //API実行 15 var https = require('https'); 16 var options = { 17 hostname: 'example.com', 18 port: 443, 19 path: '/', 20 method: 'GET' 21 }; 22 23 var req = https.request(options, (res) => { 24 console.log('statusCode:', res.statusCode); 25 console.log('headers:', res.headers); 26 27 res.on('data', chunk => { 28 result = result +chunk; 29 }); 30 res.on('end', () => { 31 var response = parseData(); 32 callback(response); 33 }); 34 }); 35 req.on('error', (e) => { 36 console.error(e); 37 }); 38 req.end(); 39} 40 41function parseData(result) { 42 //API実行結果パース 43 return parsedResult; 44}

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

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

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

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

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

mit0223

2017/09/13 06:51

このコードのとおりであれば、callback の呼び出しが getAPIData の中で同期的なので、 obj は書き換わり、 console.log でも見えると思います。 callback が非同期に呼ばれるのであれば、コード例をそういう風に書いてもらえますか。callback が非同期であれば、consol.log で書き換わったのが見えないのは当然なので、その解説を回答します。
strawberry

2017/09/13 07:07

ご指摘いただきありがとうございます。API実行と結果のパース部分を詳しく書き直しました。
guest

回答1

0

ベストアンサー

JavaScript のコールバックは、殆どの場合、非同期に呼び出されます。非同期に呼び出されるというのは、それを呼び出した一連の処理が終わってから、そのタイミングになったら呼び出されるということです。例示されているコードですと、var req = https.request(options, (res) => {の第二引数は非同期のコールバックですので、ここの処理が行われるのは、トップレベルの処理がすべて終わったあとになります。

処理される順番で書きますと、最初に実行されるのは

javascript

1getAPIData(request,obj, コールバック 2}); 3 4console.log(obj);//{hoge:"hoge"}

ここまでです。この時点ですでに{hoge:"hoge"}が出力されてしまってます。function(result,obj){の部分はコールバックですので、まだ呼ばれません。この時点で質問者様の想定とは動きが異なっていると思います。

次に HTTP の通信でレスポンスが着信すると、httpd.request の第二引数に指定されたコールバックが呼ばれます。

javascript

1 (res) => { 2 console.log('statusCode:', res.statusCode); 3 console.log('headers:', res.headers); 4 5 res.on('data', コールバック); 6 res.on('end', コールバック); 7 }

次に、データの読み込みが終わったら、res.on('data'のコールバックchunk => {result = result +chunk;}が実行され、データが終了したら、res.on('end'のコールバック() => {var response = parseData();callback(response);}が実行されます。

そこで、お待ちかねの callback が呼ばれ、

javascript

1function(result,obj){ 2 //処理内容 3 console.log(obj);//{hoge: "hoge"}; 4 Object.assign(obj,{result: result}) 5 console.log(obj);//{hoge: "hoge", result: "result"} 6}

が実行されます。

長々と書きましたが、結論から言うと、グローバル変数の obj の内容は書き換わっています。トップレベルの console.log が実行されるタイミングではまだ書き換わってないだけです。

投稿2017/09/13 08:23

mit0223

総合スコア3401

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

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

strawberry

2017/09/13 09:08

とても細かくわかりやすい解説をありがとうございます!実行順序に関しての理解が不足していました。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問