192

jQueryでは、の呼び出し(または他のタイプの反復コールバック)が完了した後に、コールバックを呼び出したり、イベントをトリガーしたりすることができますか?.each()

たとえば、この「フェードアンドリムーブ」を完了させたい

$(parentSelect).nextAll().fadeOut(200, function() {
    $(this).remove();
});

いくつかの計算を行い、の後に新しい要素を挿入する前$(parentSelect)。既存の要素がまだjQueryに表示されていて、任意の時間(要素ごとに200)のスリープ/遅延がせいぜい脆弱な解決策のように見える場合、私の計算は正しくありません。

イベントコールバックに必要なロジックは簡単に作成できますが、上記の反復が完了し.bind()た後にをクリーンに呼び出す方法がわかりません。明らかに、トリガーは複数回起動するため、反復内でトリガーを呼び出すことはできません。.trigger()

の場合$.each()、データ引数の最後に何かを追加することを検討しました(反復本体で手動で検索しました)が、それを強制されるのは嫌なので、他のエレガントなものがあることを望んでいました反復コールバックに関してフローを制御する方法。

4

12 に答える 12

192

おそらく遅いですが、このコードは機能すると思います...

$blocks.each(function(i, elm) {
 $(elm).fadeOut(200, function() {
  $(elm).remove();
 });
}).promise().done( function(){ alert("All was done"); } );
于 2012-01-20T12:17:12.500 に答える
170

@tvの答えに代わるもの:

var elems = $(parentSelect).nextAll(), count = elems.length;

elems.each( function(i) {
  $(this).fadeOut(200, function() { 
    $(this).remove(); 
    if (!--count) doMyThing();
  });
});

.each()それ自体が同期していることに注意してください。呼び出しに続くステートメントは、呼び出しが完了した.each()後にのみ実行されます。ただし、反復で開始された.each()非同期操作は、もちろん独自の方法で続行されます。これがここでの問題です。要素をフェードする呼び出しはタイマー駆動のアニメーションであり、それらは独自のペースで継続します。.each()

したがって、上記の解決策は、フェードしている要素の数を追跡します。の各呼び出し.fadeOut()は、完了コールバックを取得します。コールバックが、関連するすべての元の要素を介してカウントされていることに気付いた場合、すべてのフェードが終了したことを確信して、後続のアクションを実行できます。

これは4年前の回答です(2014年のこの時点で)。これを行うための最新の方法は、おそらくDeferred / Promiseメカニズムを使用することですが、上記は単純であり、問​​題なく機能するはずです。

于 2010-03-01T19:09:51.413 に答える
156

わかりました、これは事実の少し後かもしれませんが、.promise()もあなたが求めているものを達成するはずです。

約束のドキュメント

私が取り組んでいるプロジェクトの例:

$( '.panel' )
    .fadeOut( 'slow')
    .promise()
    .done( function() {
        $( '#' + target_panel ).fadeIn( 'slow', function() {});
    });

:)

于 2011-12-21T02:17:05.773 に答える
28

JavaScriptは同期的に実行されるため、後に配置するものはすべて、完了each()するまで実行されませんeach()

次のテストを検討してください。

var count = 0;
var array = [];

// populate an array with 1,000,000 entries
for(var i = 0; i < 1000000; i++) {
    array.push(i);
}

// use each to iterate over the array, incrementing count each time
$.each(array, function() {
    count++
});

// the alert won't get called until the 'each' is done
//      as evidenced by the value of count
alert(count);

アラートが呼び出されると、アラートは完了するまで実行されないため、カウントは1000000になりeach()ます。

于 2010-03-01T20:05:28.523 に答える
6

私は次のようなものを使用しています:

$.when(
           $.each(yourArray, function (key, value) {
                // Do Something in loop here
            })
          ).then(function () {
               // After loop ends.
          });
于 2020-04-20T09:17:17.360 に答える
5

配列を処理する応答がたくさん見つかりましたが、jsonオブジェクトは処理しませんでした。私の解決策は、カウンターをインクリメントしながらオブジェクトを1回反復し、次にオブジェクトを反復処理してコードを実行するときに、2番目のカウンターをインクリメントすることでした。次に、2つのカウンターを比較して、ソリューションを取得します。私はそれが少し不格好であることを知っていますが、私はこれまでのところよりエレガントな解決策を見つけていません。これは私のサンプルコードです:

var flag1 = flag2 = 0;

$.each( object, function ( i, v ) { flag1++; });

$.each( object, function ( ky, val ) {

     /*
        Your code here
     */
     flag2++;
});

if(flag1 === flag2) {
   your function to call at the end of the iteration
}

私が言ったように、それは最もエレガントではありませんが、それは機能し、うまく機能し、私はまだより良い解決策を見つけていません。

乾杯、JP

于 2011-03-01T17:15:56.660 に答える
1

いくつかの手順を実行する場合は、これでうまくいく可能性があります。ただし、アニメーションが順番に終了するかどうかによって異なります。それは問題ではないと思います。

var elems = $(parentSelect).nextAll();
var lastID = elems.length - 1;

elems.each( function(i) {
    $(this).fadeOut(200, function() { 
        $(this).remove(); 
        if (i == lastID) {
           doMyThing();
        }
    });
});
于 2010-03-01T19:02:24.907 に答える
0

どうですか

$(parentSelect).nextAll().fadeOut(200, function() { 
    $(this).remove(); 
}).one(function(){
    myfunction();
}); 
于 2010-03-01T20:33:42.263 に答える
0

リクエストを機能させるには、残りのリクエストをキューに入れる必要があります。

var elems = $(parentSelect).nextAll();
var lastID = elems.length - 1;

elems.each( function(i) {
    $(this).fadeOut(200, function() { 
        $(this).remove(); 
        if (i == lastID) {
            $j(this).queue("fx",function(){ doMyThing;});
        }
    });
});
于 2010-12-21T19:04:17.690 に答える
0

私は同じ問題に遭遇し、次のコードのような解決策で解決しました:

var drfs = new Array();
var external = $.Deferred();
drfs.push(external.promise());

$('itemSelector').each( function() {
    //initialize the context for each cycle
    var t = this; // optional
    var internal = $.Deferred();

    // after the previous deferred operation has been resolved
    drfs.pop().then( function() {

        // do stuff of the cycle, optionally using t as this
        var result; //boolean set by the stuff

        if ( result ) {
            internal.resolve();
        } else {
            internal.reject();
        }
    }
    drfs.push(internal.promise());
});

external.resolve("done");

$.when(drfs).then( function() {
    // after all each are resolved

});

このソリューションは、次の問題を解決します。Deferredオブジェクトを使用して、.each()反復で開始された非同期操作を同期します。

于 2017-03-05T09:42:11.123 に答える
0

応答が遅いかもしれませんが、これを処理するパッケージがあり ますhttps://github.com/ACFBentveld/Await

 var myObject = { // or your array
        1 : 'My first item',
        2 : 'My second item',
        3 : 'My third item'
    }

    Await.each(myObject, function(key, value){
         //your logic here
    });

    Await.done(function(){
        console.log('The loop is completely done');
    });
于 2018-06-21T11:25:42.000 に答える
0
var count = $(parentSelect).length;

$(parentSelect).each(function () {

   //do you task here

   if (!--count) {

     //do the cleanup task

     alert ('Reached the end of each loop')
   }

});
于 2022-03-04T08:51:50.767 に答える