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

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

ただいまの
回答率

90.49%

  • JavaScript

    16966questions

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

  • Node.js

    1934questions

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

  • 非同期処理

    115questions

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

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,983

strawberry

score 7

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

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

"use strict";
var obj = {hoge: "hoge"};

getAPIData(request,obj, function(result,obj){
  //処理内容
  console.log(obj);//{hoge: "hoge"};
  Object.assign(obj,{result: result})
  console.log(obj);//{hoge: "hoge", result: "result"}
});

console.log(obj);//{hoge:"hoge"}

function getAPIData(request,obj, callback) {
  //API実行
  var https = require('https');
  var options = {
    hostname: 'example.com',
    port: 443,
    path: '/',
    method: 'GET'
  };

  var req = https.request(options, (res) => {
    console.log('statusCode:', res.statusCode);
    console.log('headers:', res.headers);

    res.on('data', chunk => {
      result = result +chunk;
    });
    res.on('end', () => {
      var response = parseData();
      callback(response);
    });
  });
  req.on('error', (e) => {
    console.error(e);
  });
  req.end();
}

function parseData(result) {
  //API実行結果パース
 return parsedResult;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mit0223

    2017/09/13 15:51

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

    キャンセル

  • strawberry

    2017/09/13 16:07

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

    キャンセル

回答 1

checkベストアンサー

+1

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

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

getAPIData(request,obj, コールバック
});

console.log(obj);//{hoge:"hoge"}


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

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

 (res) => {
    console.log('statusCode:', res.statusCode);
    console.log('headers:', res.headers);

    res.on('data', コールバック);
    res.on('end', コールバック);
  }


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

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

function(result,obj){
  //処理内容
  console.log(obj);//{hoge: "hoge"};
  Object.assign(obj,{result: result})
  console.log(obj);//{hoge: "hoge", result: "result"}
}


が実行されます。

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/13 18:08

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

    キャンセル

関連した質問

同じタグがついた質問を見る

  • JavaScript

    16966questions

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

  • Node.js

    1934questions

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

  • 非同期処理

    115questions

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