web-dev-qa-db-ja.com

jQuery:Ajax呼び出しが成功した後にデータを返す

私はこのようなものを持っています、それはそれが私に値、文字列を返すスクリプトへの単純な呼び出しです。

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {
         return data; 
      }
   });
}

しかし、私がこのようなものを呼べば

var output = testAjax(svar);  // output will be undefined...

それでどうやって値を返すことができますか?以下のコードも動作しないようです...

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {

      }
   });
   return data; 
}
421
Francesco

関数からデータを返す唯一の方法は、非同期呼び出しではなく同期呼び出しを行うことですが、応答を待っている間はブラウザがフリーズします。

結果を処理するコールバック関数を渡すことができます。

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

このようにそれを呼ぶ:

testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.
354
Guffa

注:この回答は2010年2月に作成されました。
下部にある2015、2016、2017年の更新を参照してください。

非同期の関数からは何も返せません。返すことができるのはpromiseです。これらの質問への回答で、jQueryでの約束の仕組みを説明しました。

なぜを説明できたら、データを返したいのか、後でそれをどうしたいのか、それを行う方法についてより具体的な答えを提供できるかもしれません。

一般的に、次の代わりに:

function testAjax() {
  $.ajax({
    url: "getvalue.php",  
    success: function(data) {
      return data; 
    }
  });
}

次のようにtestAjax関数を作成できます。

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

次に、このような約束を得ることができます。

var promise = testAjax();

約束を保存し、それを渡したり、関数呼び出しの引数として使用したり、関数から返すことができますが、最終的にse AJAX呼び出し、次のようにする必要があります。

promise.success(function (data) {
  alert(data);
});

(簡略化された構文については、以下の更新を参照してください。)

この時点でデータが利用可能な場合、この関数はすぐに呼び出されます。そうでない場合は、データが利用可能になるとすぐに呼び出されます。

このすべてを行うことの全体的なポイントは、データが非同期であるため、$。ajaxの呼び出し直後にデータが利用できないことです。 Promisesは言うべき機能の素敵な抽象化です。まだデータを持っていないのでデータを返すことができず、ブロックして待機させたくないので、ここにpromise代わりに、後で使用したり、他の人に渡して完了させることができます。

こちらをご覧ください DEMO

更新(2015)

現在(2015年3月現在)、jQuery Promiseは Promises/A +仕様 と互換性がありません。これは、他の Promises/A +準拠の実装 とうまく連携しない可能性があることを意味します。

ただし、今後のバージョン3.xのjQuery Promise は、Promises/A +仕様と互換性があります( Benjamin Gruenbaum に感謝します)。現在(2015年5月現在)、jQueryの安定バージョンは1.xおよび2.xです。

上記(2011年3月)で説明したのは、 jQuery Deferred Objects を使用して、値を返すことで同期コードで実現される非同期処理を行う方法です。

ただし、同期関数呼び出しでは2つのことができます。値を返すことができる場合(可能な場合)、または例外をスローすることができます(値を返すことができない場合)。 Promises/A +は、同期コードでの例外処理と同じくらい強力な方法で、これらのユースケースの両方に対処します。 jQueryバージョンは値を返すのと同等の処理を適切に行いますが、複雑な例外処理と同等の処理には多少問題があります。

特に、同期コードでの例外処理のポイントは、単にニースメッセージをあきらめることではなく、問題を修正して実行を継続すること、またはプログラムの他の部分の同じまたは異なる例外を再スローすることですハンドル。同期コードには、呼び出しスタックがあります。非同期呼び出しでは、Promises/A +仕様で要求されているプロミス内での高度な例外処理は不要であり、複雑なユースケースでも意味のある方法でエラーと例外を処理するコードを書くのに役立ちます。

JQueryと他の実装の違い、およびjQuery PromiseをPromises/A +準拠に変換する方法については、Kris Kowal et al。による jQueryからの移行 を参照してください。 Qライブラリwikiおよび PromisesがJavaScriptで届きます HTML5 RocksのJake Archibaldによって。

本当の約束を返す方法

上記の私の例の関数:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

jqXHRオブジェクトを返します。これはjQuery Deferred Object です。

本当の約束を返すようにするには、Q wikiのメソッドである を使用して に変更できます。

function testAjax() {
  return Q($.ajax({
      url: "getvalue.php"
  }));
}

または、 HTML5 Rocks記事のメソッドを使用して

function testAjax() {
  return Promise.resolve($.ajax({
      url: "getvalue.php"
  }));
}

このPromise.resolve($.ajax(...))は、promiseモジュールのドキュメントで説明されている であり、 であり、 ES6 Promise.resolve() で動作するはずです。

今日ES6 Promiseを使用するには、Jake Archibaldによる es6-promiseモジュールのpolyfill() を使用できます。

ポリフィルなしでES6 Promiseを使用できる場所については、 使用できますか:Promises を参照してください。

詳細については、以下を参照してください。

JQueryの未来

JQueryの将来のバージョン(3.xから-2015年5月現在の安定バージョンは1.xおよび2.xです)は、 Promises/A +仕様と互換性がありますBenjamin Gruenbaumに感謝します) コメントで指摘してください)。 "既に決定した2つの変更は、Deferred実装のPromise/A +互換性です[...]"jQuery 3.0とWeb開発の将来 )。詳細については、 jQuery 3.0:The Next Generations Dave Methvin氏および jQuery 3.0:Internet Explorerの少ない相互運用性 Paul Krill氏による。

興味深い話

更新(2016)

ECMA-262、第6版、セクション14.2に新しい構文があります と呼ばれる 矢印関数 は、上記の例をさらに単純化するために使用できます。

次の代わりにjQuery APIを使用します。

promise.success(function (data) {
  alert(data);
});

あなたは書ける:

promise.success(data => alert(data));

またはPromises/A + APIを使用して:

promise.then(data => alert(data));

常に次のいずれかの拒否ハンドラを使用することを忘れないでください。

promise.then(data => alert(data), error => alert(error));

または:

promise.then(data => alert(data)).catch(error => alert(error));

Promiseで常に拒否ハンドラを使用する必要がある理由を確認するには、この回答を参照してください。

もちろん、この例では、コールバックと同じ引数でalertを呼び出しているだけなので、promise.then(alert)だけを使用できますが、矢印構文はより一般的で、次のように記述できます。

promise.then(data => alert("x is " + data.x));

すべてのブラウザがまだこの構文をサポートしているわけではありませんが、コードがどのブラウザで実行されるかが確実な場合があります。 Chrome拡張を記述する場合Firefoxアドオン 、またはElectron、NW.js、AppJSを使用したデスクトップアプリケーション( この回答を参照 詳細については)。

矢印関数のサポートについては、以下を参照してください。

更新(2017)

このコードの代わりに新しいawaitキーワードを持つ非同期関数と呼ばれるさらに新しい構文があります:

functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

あなたが書くことができます:

try {
    let data = await functionReturningPromise();
    console.log('Data:', data);
} catch (error) {
    console.log('Error:', error);
}

asyncキーワードで作成された関数内でのみ使用できます。詳細については、以下を参照してください。

ブラウザーでのサポートについては、以下を参照してください。

Nodeでのサポートについては、以下を参照してください。

asyncおよびawaitのネイティブサポートがない場所では、Babelを使用できます。

または、わずかに異なる構文で、coまたはBluebirdコルーチンのようなジェネレーターベースのアプローチ:

詳細情報

詳細については、約束に関するその他の質問:

387
rsp

あなたはfalseに非同期オプションを追加することができますAjax呼び出しの外側に戻ります。

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}
166
Ging3r

Idkあなたが皆さんそれを解決したら私はそれをする別の方法をお勧めします、そしてそれはうまくいきます:)

    ServiceUtil = ig.Class.extend({
        base_url : 'someurl',

        sendRequest: function(request)
        {
            var url = this.base_url + request;
            var requestVar = new XMLHttpRequest();
            dataGet = false;

            $.ajax({
                url: url,
                async: false,
                type: "get",
                success: function(data){
                    ServiceUtil.objDataReturned = data;
                }
            });
            return ServiceUtil.objDataReturned;                
        }
    })

そのため、ここでの主な考え方は、async:falseを追加することで、データが取得されるまですべて待機することです。それからそれをクラスの静的変数に代入すれば、すべてが魔法のように機能します:)

0
user1509803