これに似たものがあり、これは値、つまり文字列を返すスクリプトへの単純な呼び出しです。
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。
詳細については以下を参照してください:
- http://bugs.jquery.com/ticket/14510
- 参考:
- https://gist.github.com/domenic/3889970
- http://promises-aplus.github.io/promises-spec/
- http://www.html5rocks.com/en/tutorials/es6/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 の減少ポール・クリル著。
興味深い講演
- ブーム、プロミセス/A+が誕生ドメニック・デニコラ (JSConfUS 2013)
- コールバック地獄からの救済マイケル・ジャクソンとドメニック・デニコラ (HTML5DevConf 2013)
- JavaScript の約束デイビッド・M・リー(2014年11月)
アップデート (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を使用したデスクトップアプリケーション(この答え詳細については)。
矢印関数のサポートについては、以下を参照してください。
- http://caniuse.com/#feat=arrow-functions
- http://kangax.github.io/compat-table/es6/#test-arrow_functions
アップデート (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
。詳細については、以下を参照してください。
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
ブラウザでのサポートについては、以下を参照してください。
Node でのサポートについては、以下を参照してください。
ネイティブサポートがなくasync
、await
Babel を使用できる場所:
または、少し異なる構文で、co
または Bluebird コルーチンのようなジェネレータ ベースのアプローチを使用します。
より詳しい情報
詳細については、Promise に関するその他の質問をご覧ください。
- promise-resolution とは別の promise 呼び出し
- Q 約束の遅延
- Promiseの代わりにPromiseの結果を返す
- プロミスの結果からモジュールをエクスポートする
- プロミス解決の何が問題なのでしょうか?
- プロミスブロックからの関数の戻り値
- プロミス内でステータスを返すにはどうすればいいですか?
- Promise の拒否を非同期的に処理するのは控えるべきでしょうか?
- JavaScript の deferred/promise の概念は新しいものですか、それとも関数型プログラミングの伝統的な部分ですか?
- これらの関数を Promise で連結するにはどうすればよいでしょうか?
- JavaScript の Promise.all: すべての Promise の解決値を取得するにはどうすればよいでしょうか?
- Promise.all が未定義である理由
- 関数はJavaScriptのpost/getからnullを返します
- promisifyAll によって作成された then チェーン内で cancel() を使用する
- エラーを起こさずに、関数以外のパラメータを Promise.then() に渡すことができるのはなぜですか?
- Promisesパターンを実装する
- 約束と実績
- プロミスで 2 つの URL をスクレイピングする際の問題
- http.request は 'end' イベントで return を指定してもデータを返さない
- async.each が Promise 使用時に反復しない
- jQuery jqXHR - 連鎖呼び出しをキャンセルし、エラー チェーンをトリガーする
- Promiseとサーバー応答を正しく処理する方法
- 関数自体内のすべての操作が完了する前に、関数呼び出しから値を返しますか?
- APIエンドポイント内でのsetTimeoutの解決
- 関数の非同期待機
- AJAX 呼び出しデータを返す JavaScript 関数
- async/await を使用した try/catch ブロック
- jQuery Deferred が、resolve/done コールバックを順番に呼び出さない
- Ajaxからデータを返すと奇妙なオブジェクトが生成される
- javascript - 同期モジュールと非同期モジュールの仕様があるのはなぜですか?