jQuery: ajax 呼び出しが成功した後にデータを返す [重複] 質問する

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; 
}

ベストアンサー1

注: この回答は 2010 年 2 月に作成されました。2015
年、2016 年、2017 年の更新内容は下部をご覧ください。

非同期関数からは何も返せません。返せるのは promise ですこれらの質問に対する回答で、jQuery での promise の仕組みについて説明しました。

なぜデータを返却したいのか、また後でそのデータで何をしたいのかを説明していただければ、その方法についてより具体的な回答ができるかもしれません。

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

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

testAjax 関数は次のように記述できます。

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

すると、次のように Promise を取得できます。

var promise = testAjax();

プロミスを保存したり、渡したり、関数呼び出しで引数として使用したり、関数から返したりできますが、最終的にAJAX 呼び出しによって返されたデータを使用する場合は、次のようにする必要があります。

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

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

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

これらすべてを行う主な目的は、$.ajax の呼び出しが非同期であるため、データがすぐには利用できないことです。Promise は、関数が次のように言うための優れた抽象化です。「まだデー​​タを取得していないため、データを返すことができません。ブロックして待たせたくないので、代わりにpromise を用意して、後で使用したり、他の誰かに渡して済ませたりすることができます。」

これを見てデモ

アップデート (2015)

現在(2015年3月現在)jQuery Promiseは約束/A+仕様つまり、彼らは他の人とうまく協力できないかもしれないPromises/A+準拠の実装

しかし、jQuery Promisesは次期バージョン3.xではPromises/A+仕様と互換性を持つ予定です(ベンジャミン・グルンバウムご指摘ありがとうございます。現在 (2015 年 5 月現在)、jQuery の安定バージョンは 1.x と 2.x です。

上記(2011年3月)で説明したのは、jQuery 遅延オブジェクト同期コードでは値を返すことによって実現される操作を非同期で実行します。

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

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

jQueryと他の実装の違い、およびjQueryのPromiseをPromises/A+準拠に変換する方法については、以下を参照してください。jQueryから来たクリス・コワル他によるQライブラリWikiとJavaScript に Promise が登場HTML5 Rocks の Jake Archibald による記事。

本当の約束を返す方法

上記の例の関数:

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

jQueryであるjqXHRオブジェクトを返します遅延オブジェクト

実際のPromiseを返すようにするには、次のように変更します。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モジュールのドキュメントで説明されているそしてそれはうまくいくはずですES6Promise.resolve()

ES6 Promisesを今日使うには、es6-promiseモジュールのpolyfill()ジェイク・アーチボルド著。

ポリフィルなしで ES6 Promise を使用できる場所を確認するには、以下を参照してください。使えるもの: Promises

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

jQueryの将来

jQueryの将来のバージョン(3.xから始まり、2015年5月現在の安定バージョンは1.xと2.x)は、約束/A+仕様(感謝ベンジャミン・グルンバウムコメントで指摘してくださった皆様に感謝します。「すでに決定した 2 つの変更は、Deferred 実装の Promise/A+ 互換性です [...]」 (jQuery 3.0 と Web 開発の未来詳細については以下を参照してください。jQuery 3.0: 次世代デイブ・メスビンとjQuery 3.0: 相互運用性の向上、Internet Explorer の減少ポール・クリル著。

興味深い講演

アップデート (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 で拒否ハンドラを常に使用する必要がある理由については、次の回答を参照してください。

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

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

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

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

アップデート (2017)

現在、新しいawaitキーワードを持つ async functions と呼ばれるさらに新しい構文があり、次のコードの代わりに次のコードが使用されます。

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 でのサポートについては、以下を参照してください。

ネイティブサポートがなくasyncawaitBabel を使用できる場所:

または、少し異なる構文で、coまたは Bluebird コルーチンのようなジェネレータ ベースのアプローチを使用します。

より詳しい情報

詳細については、Promise に関するその他の質問をご覧ください。

おすすめ記事