私は似たような質問を探して解決策を試すのに非常に多くの時間を費やしてきたので、誰かが解決策を持っていることを願っています。
基本的に、関数a()が完了したときに通知を受け取りたいのですが、問題は、関数にajax呼び出しと、再びajaxを含むb()を呼び出すループが含まれていることです。コール。
FIDDLEで更新: http://jsfiddle.net/hsyj7/1/
そのようです:
// called by main()
function a() {
return $.ajax("http://url1").pipe(function(data){
for (var i = 0; i < 2; i++) {
console.log('a called');
b();
}
});
}
// called by a()
function b() {
for (var i = 0; i < 2; i++) {
$.ajax("http://url2", function(data){
// do something
console.log('b called');
}
}
}
function main(){
$.when(a()).done(function(){
console.log('all completed');
});
}
それで私が見たいのは、おそらく上部にa()の両方の呼び出しがある:
a called
b called
b called
a called
b called
b called
all completed
代わりに私は得る
a called
all completed
b called
b called
またはそのいくつかの変形。
上記のコードには、ループとb()の両方で遅延機能が欠落していることを認識しています。私が試したいくつかのバリアントでは、main()のdone()ハンドラーが呼び出されることはありません。
誰かがこれを行う方法を知っていますか?
ええ、Deferred
を使用するのがそれを行う方法です:
function a() {
var def = $.Deferred();
$.ajax("http://url1").done(function(data){
var requests = [];
for (var i = 0; i < 2; i++) {
requests.Push(b());
}
$.when.apply($, requests).then(function() { def.resolve(); });
});
return def.promise();
}
// called by a()
function b() {
var def = $.Deferred(),
requests = [];
for (var i = 0; i < 2; i++) {
requests.Push($.ajax("http://url2").done(function(data){
// do something
console.log('b called');
});
}
$.when.apply($, requests).then(function() { def.resolve(); });
return def.promise();
}
function main(){
$.when(a()).done(function(){
console.log('all completed');
});
}
//編集:置換.pipe
と.done
。
質問は古いかもしれませんが、正しい解決策がまだないので、ここに答えを置きます。 .then
(以前は.pipe
でした)を使用してpromiseを適切にチェーンし、要求された結果を達成します。
function a() {
return $.ajax("http://url1").done(function(data){
console.log('a called');
}).then(function(){
return $.when(b(), b()); // no loop for simplicity
});
}
function b() {
return $.ajax("http://url2").done(function(data){
console.log('b called');
});
}
function main(){
a().done(function(){
console.log('all completed');
}, function() {
console.log('an error occured!');
});
}
ネスト/構造が変更される可能性のある場所で利用可能な結果データに応じて、全体的な順序は正しいです。
より高いコンテキストにあるArrayを使用して、Promise/Deferredオブジェクトをプッシュすることができます。次に、jQuery.when
をFunction.prototype.apply
と一緒に使用して、すべてのエントリを引数として渡すことができます。
(function() {
var promises = [ ],
when = Function.prototype.apply.bind( jQuery.when, null );
function a() {
promises.Push($.ajax("http://url1").pipe(function(data){
for (var i = 0; i < 2; i++) {
console.log('a called');
b();
}
}));
return promises;
}
function b() {
for (var i = 0; i < 2; i++) {
promises.Push($.ajax("http://url2", function(data) {
// do something
console.log('b called');
}));
}
}
function main() {
promises = [ ];
when( a() ).done(function(){
console.log('all completed');
});
}
}());
これはコールバックで修正できると思いますが、フィドルは私があなたをチェックするのに本当に役立ちました。
// called by main()
function a(callback) {
//set this to the number of loops that is going to happen
var number = 2;
return $.ajax("http://url1", function(data){
console.log('a called');
for (var i = 0; i < number ; i++) {
b();
if(number===i){
callback();
}
}
}
}
function main(){
a(function(){
//Function or code you want to run on completion..
});
}
これがうまくいかない場合は許してください、しかし私はそれが正しい方向だと思います。