web-dev-qa-db-ja.com

関数内でのみアクセス可能な$ .getJSON関数中に設定される変数

これは、よりスコープの質問かもしれません。 $ .getJSON関数内でJSONオブジェクトを設定しようとしていますが、コールバックの外部でそのオブジェクトを使用できる必要があります。

_var jsonIssues = {};  // declare json variable

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues not accessible here
_

このような同様の質問が別の投稿で尋ねられ、コンセンサスは、JSONオブジェクトで行う必要があることはコールバック関数内で行う必要があり、他のどこからもアクセスできないということでした。 $ .getJSONコールバック以外のJSONオブジェクトに引き続きアクセス/操作する方法はありませんか?変数を返す、またはグローバルを設定するのはどうですか?

助けていただければ幸いです。これは正しくないようです...

更新:

$ .ajax()非同期設定をfalseに設定し、同じコードを実行しましたが、運はありませんでした。私が試したコードは以下です:

_var jsonIssues = {};  // declare json variable

$.ajax({ async: false });

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues still not accessible here
_

また、グローバル変数が正常に機能するといういくつかの応答がありました。このコードはすべて$(document).ready(function() {内にあることを明確にする必要があります。グローバル変数を設定するには、document.readyの前に宣言するだけですか?など:

_var jsonIssues = {};

$(document).ready(function() {

  var jsonIssues = {};  // declare json variable

  $.getJSON("url", function(data) {
      jsonIssues = data.Issues;
  });

  // now accessible?
}
_

Document.readyで宣言された変数は、$。getJSONコールバック関数などのサブ関数を含め、document.readyの任意の部分で「グローバルに」アクセスおよび変更可能であるべきだという印象を受けました。 javascript変数のスコープについて調べる必要があるかもしれませんが、目的を簡単に達成できるとは思えません。すべての回答をありがとう。

PDATE#2:以下の回答に与えられたコメントごとに、$。ajaxを使用しました代わりに .getJSONを使用して、望みの結果を達成しました。コードは次のとおりです。

_var jsonIssues = {};
    $.ajax({
        url: "url",
        async: false,
        dataType: 'json',
        success: function(data) {
            jsonIssues = data.Issues;
        }
    });

    // jsonIssues accessible here -- good!!
_

私の回答に対するフォローアップのコメントをいくつか(そしてそれらすべてに感謝します)。これを行うための私の目的は、最初にJSONオブジェクトに、ユーザーが削除および保存できる問題のリストを読み込むことです。しかし、これはページ上の後続のインタラクションを介して行われ、ユーザーがJSONオブジェクトで何をしたいのかは予測できませんwithinコールバック。したがって、コールバックが完了したらアクセス可能にする必要があります。ここで私のロジックに欠陥がありますか?真剣に、私が見ていない何かがあるかもしれないので...

また、私は.ajax()jQueryドキュメントを読んでいて、asyncをfalseに設定すると、「データを同期的にロードします。リクエストがアクティブな間、ブラウザをブロックします。 」

これが進行中に、ユーザーの操作をどのようにブロックする必要があるのか​​、誰にも分かりますか?なぜそんなに心配なのですか?すべての回答に感謝します。

43
MegaMatt

$.getJSONは非同期です。つまり、呼び出し後のコードは$.getJSONは、データをフェッチして解析し、コールバックを呼び出します。

したがって、これを考えると:

a();

$.getJSON("url", function() {
    b();
});

c();

ab、およびcの呼び出しの順序は、a b c(この場合、yoが必要)またはa c b(実際に発生する可能性が高い)。

ソリューション?

同期XHRリクエスト

要求を非同期ではなく同期にします。

a();

$.ajax({
    async: false,
    url: "url",
    success: function() {
        b();
    }
});

c();

再構築コード

cへの呼び出しの後にbへの呼び出しを移動します。

a();

$.getJSON("url", function() {
    b();

    c();
});
34
strager

コールバック関数を提供するとき、そのポイントは、そのコールバックの実行を後で延期し、すぐに次のものの実行を継続することです。これは、ブラウザー内のJavaScriptのシングルスレッド実行モデルのために必要です。強制的に同期実行することは可能ですが、操作の全期間にわたってブラウザがハングします。 $ .getJSONのようなものの場合、ブラウザが応答を停止するのは非常に長い時間です。

つまり、この手続き型のパラダイムを使用する方法を見つけようとしているということです。

var foo = {};

$.getJSON("url", function(data) {
  foo = data.property;
});

// Use foo here.

コードを次のようにリファクタリングする必要がある場合:

$.getJSON("url", function(data) {
  // Do something with data.property here.
});

コールバック関数をシンプルに保ちたい場合、「何かをする」は別の関数の呼び出しである可能性があります。重要な部分は、コードを実行する前に$ .getJSONが終了するまで待っていることです。

カスタムイベントを使用して、$。getJSONの後に配置したコードがIssuesReceivedイベントをサブスクライブし、$。getJSONコールバックでそのイベントを発生させることもできます。

$(document).ready(function() {
  $(document).bind('IssuesReceived', IssuesReceived)

  $.getJSON("url", function(data) {
    $(document).trigger('IssuesReceived', data);
  });
});

function IssuesReceived(evt, data) {
  // Do something with data here.
}

更新:

または、データをグローバルに保存し、カスタムイベントを使用して、データが受信され、グローバル変数が更新されたことを通知することもできます。

$(document).ready(function() {
  $(document).bind('IssuesReceived', IssuesReceived)

  $.getJSON("url", function(data) {
    // I prefer the window.data syntax so that it's obvious
    //  that the variable is global.
    window.data = data;

    $(document).trigger('IssuesReceived');
  });
});

function IssuesReceived(evt) {
  // Do something with window.data here.
  //  (e.g. create the drag 'n drop interface)
}

// Wired up as the "drop" callback handler on 
//  your drag 'n drop UI.
function OnDrop(evt) {
  // Modify window.data accordingly.
}

// Maybe wired up as the click handler for a
//  "Save changes" button.
function SaveChanges() {
  $.post("SaveUrl", window.data);
}

更新2:

これに応えて:

これが進行中に、ユーザーの操作をどのようにブロックする必要があるのか​​、誰にも分かりますか?なぜそんなに心配なのですか?すべての回答に感謝します。

同期AJAX呼び出しでブラウザをブロックしないようにする必要がある理由は、ブロックされたJavaScriptスレッドがブラウザ内の他のすべてもブロックするためですタブや他のウィンドウです。つまり、スクロール、ナビゲーション、何もありません。すべての意図と目的において、ブラウザがクラッシュしたように見えます。ご想像のとおり、このように動作するページは重要ユーザーへの迷惑。

9
Dave Ward

たぶんこの作品は、私にとってはうまくいく.. :)

$variable= new array();

$.getJSON("url", function(data){
asignVariable(data);
}

function asignVariable(data){
$variable = data;
}

console.log($variable);

それがあなたを助けることを願っています.. :)

5
Alexander

あなたは約束でこれに近づくことができます:

var jsonPromise = $.getJSON("url")

jsonPromise.done(function(data) {
    // success
    // do stuff with data
});

jsonPromise.fail(function(reason) {
    // it failed... handle it
});

// other stuff ....

jsonPromise.then(function(data) {
    // do moar stuff with data
    // will perhaps fire instantly, since the deferred may already be resolved.
});

これは非常に単純で、非同期コードをより重要に感じさせる実行可能な方法です。

4
Björn Roberg

「しかし、これはページ上の後続のインタラクションを介して行われ、ユーザーがコールバック内のJSONオブジェクトで何をしたいのかを予測することはできません。」

コールバックは、ユーザーがデータを操作するための画面を設定する機会です。

ユーザー用にHTMLを作成または公開し、さらにコールバックを設定できます。

ほとんどの場合、どのコードも実行されません。 Ajaxページのプログラミングは、どのイベントがいつ発生するかについて考えることです。

「Sjax」ではなく「Ajax」である理由があります。非同期から同期に変更するのが苦痛な理由があります。ページの非同期を行うことが期待されています。

イベント駆動型プログラミングは、最初はイライラすることがあります。

JSで計算集中型の金融アルゴリズムを実行しました。それでも、それは同じことです-あなたはそれを小さな部分に分割し、イベントはタイムアウトです。

JavaScriptのアニメーションもイベント駆動型です。実際、スクリプトが制御を繰り返し放棄しない限り、ブラウザは動きさえ表示しません。

1
Nosredna