2011-10-20 17 views
1

コールバック、スコープ、クロージャに関する多くの質問があります。これが重複している場合は、事前にお詫び申し上げます。反復中のコールバックスコープ

私は、いくつかの非同期アクションを実行してコールバックを発行する関数を呼び出すループをそれぞれ持っています。私はコールバックが発生したときに(明らかに)スコープを失います。私がやったのは、ループの中のアイテムを関数に渡してコールバックで返すので、必要なスコープがあるからです。それはこれを行うための最善の方法ですか?私は過度に複雑なものを探しているわけではありません。私はちょうど私がどのような "つかの間"に遭遇するつもりはないことを確認したい。あなたが持っているもの

function doSomething(varA, varB, self, callback) { 
    // do a lot of ajax stuff 
    callback(varA + varB, self); 
} 

$.each($('.selected'), function(i, item) { 
    doSomething('a', 'b', item, function(retVal, self) { 
    // process retVal and self 
    } 
} 

答えて

2

は細かいが、1つの事を探します:.each()の代わりに$.each()を使用します。これを試してみてください:

$('.selected').each(function(i, item) { 
    doSomething('a', 'b', item, function(retVal, self) { 
    // process retVal and self 
    } 
} 
+0

私が持っていたよりも良い構文。 – Jay

1

をあなたはdoSomething内の要素参照を必要としない場合は、あなたがこの中にクロージャを作成することができ、少し整然と方法:

function doSomething(varA, varB, callback) { 
    // do a lot of ajax stuff 
    callback(varA + varB); 
} 

$.each($('.selected'), function() { 
    var self = this; 
    doSomething('a', 'b', function(retVal) { 
    // process retVal and self 
    } 
}); 
+0

私は実際にこのようにしてクロージャーを使ってみました。自己がループ内にあった場合、スコープは失われてしまいます。ループ外に移動した場合、コールバックが発生する前にループが複数回実行され(selfの値が変更された)問題は、ループが連続して進行し、コールバックがいつでも発生することです。 – Jay

0

主な「落とし穴」の人が実行into into ajaxとループは、後で実行される関数の中で反復変数を再利用しようとしています。例えば

for (var i in col) { 
    $.ajax({ 
    url: '...' + i + '.html', 
    success: function() { 
     console.log(i); // Why is i different??? 
    } 
    }); 
} 

このsuccessコールバックのすべての間で共有さiの1つのインスタンスがあるので、「落とし穴」が発生します。

「反復」レベルごとに1つずつiがあります。だから、この邪魔はあなたを襲わないでしょう。

0

callbackは、.each()ファンクション内に定義されているため、コールバック機能を使用するまでには、itemがまだ有効範囲にあります。したがって、doSomething()selfを決して使用しない場合、それを渡す必要はありません。あなただけのitemを参照することができます。コールバックは.each()の外で定義されている場合

function doSomething(varA, varB, callback) { 
    // do a lot of ajax stuff 
    callback(varA + varB); 
} 

$('.selected').each(function(i, item) { 
    doSomething('a', 'b', function(retVal) { 
    // process retVal and item 
    }); 
}); 

さて、あなたはそれをあなたがそれを持っている方法を行う必要があるだろう、itemdoSomething()に渡し:それはある

function doSomething(varA, varB, self, callback) { 
    // do a lot of ajax stuff 
    callback(varA + varB, self); 
} 
function doSomethingCallback(retVal, self) { 
    // process retVal and item 
} 

$('.selected').each(function(i, item) { 
    doSomething('a', 'b', item, doSomethingCallback); 
}); 
+0

これは私には意味があり、これは私が信じたものですが、この方法ではうまくいきませんでした。コールバックがトリガされると、iとitemの両方は未定義です。 – Jay

+0

@Jay - その場合、あなたのコードで何かが起こっています。この作業デモ:http://jsfiddle.net/gilly3/czWYK/を参照してください。 – gilly3

+0

私はそれを見ます。私の各ブロックはオブジェクト内の関数に含まれており、コールバックを発行する関数は現在のところ通常の関数です。それが問題だろうか?私の実際のコードは、XSSと他の多くのノイズのため意味がありませんが、私が意味のある例を抜け出せるかどうかはわかります。私は基本的に状態を通過させることによってそれを働かせているが、それは醜いようだ。 – Jay