2

BOLDは更新を示します。

配列stepsがあります。その内容は、アクションと要素が関連付けられたオブジェクトです。そのようです:

steps = [{action: 'click', element: <jQuery element>}, 
         {action: 'click', element: <jQuery element>}, ., ., N]

ランナーを実装したいと思います。その仕事は、配列内の各要素を実行し、要素に対して特定のアクションを実行することです。各ステップは順番に実行する必要があります。たとえば、次の場合:

 steps = [{action: 'click', element: <jQuery element representing a button>},
          {action: 'click', element: <jQuery element representing an anchor tag>}]

を実行するとrun(steps, timeout)、各ステップが実行されます。step[0].action は step[0].element に対して実行されます。step[0] が step[1] で相互作用する dom 要素を ( AJAXを使用して) 作成する可能性があるため、ランナーは特定の期間 (したがってタイムアウト) 待機する必要があり、dom をポーリングします。 step[1].element の存在。

ここに私がこれまでに持っているものの大まかな見方があります:

var run = function() { 
    $.each(steps, function(i, v) { 
        var interval = 25, 
            start = 0, 
            timeout = 3000; 
        var i = setInterval(function(timeout) { 
            start = start + interval; 
            console.log(start); 
            if ($(v).is(':visible')) { 
                v.click(); 
                console.log('clicked', v); 
                clearInterval(i);
            }   
        }, interval);
    }); 
};

上記の例では、stepsは単なる jquery オブジェクトの配列であることに注意してください。まだ目的の形式になっていません。

steps = [{action: 'click', element: <jQuery element>}, 
         {action: 'click', element: <jQuery element>}, ., ., N]

私が従わなければならない、いわば「パターン」とは何ですか?これを処理するために遅延オブジェクトを使用する必要がありますか? setTimeout、setInterval で実装されていますか? ありがとう!

最終実装

var run = function(steps, interval, timeout) {
    var timer,
        time = 0,
        i = 0;

    runSingle(steps[0]);

    function abort() {
        console.log("Run aborted");
    }

    function runSingle(step) {
        timer = setInterval(function() {
            time += interval;
            if ($(step.element).is(':visible') === true) {
                clearInterval(timer);
                time = 0;
                $(step.element).trigger(step.action);
                (i < (steps.length - 1)) && runSingle(steps[++i]);
            } else if (time >= timeout) {
                clearInterval(timer);
                abort();
            }
        }, interval);
        console.log("Performed: ", step.action, "on", step.element) 
        if (i === (steps.length - 1)) console.log("Run successful");
    }
}
4

2 に答える 2

1

まず、あなたの例では、変数は配列からのオブジェクトを表すため、 orvと言うのは意味がないことに注意してください-v.click()または$(v).is(':visible')と言いたいと思います。v.element.click()v.element.is(':visible')

actionそれがjQueryメソッドの名前であり、jQueryオブジェクトである文字列になることを意味する場合elementは、次のようにすることができます。

$.each(steps, function(i, obj) { 
    obj.element[obj.action]();
});

elementがjQueryオブジェクトの作成に使用するセレクターを表す文字列の場合、次のようになります。

$.each(steps, function(i, obj) { 
    $(obj.element)[obj.action]();
});

actionフェードインを実行したり、Ajaxを介して要素を追加したりする場合など、非同期で何かを実行する可能性がない限り、ポーリングの概念を導入する必要はありません。

あなたの例では、現在のステップを続行するかどうかに適用していると思われる唯一の基準は、現在の要素が表示されているかどうかです。その場合は、次のようなことができます。

var run = function(steps, delay, timeout) {
             var i = 0,
                 nextStep = function() {
                    if (i < steps.length) {
                       var step = steps[i],
                           retryDelay = 25,
                           retryTotal = 0,
                           intervalId = setInterval(function() {
                              retryTotal += retryDelay;
                              var $el = $(step.element);
                              if ($el.is(':visible')) { 
                                $el[step.action](); 
                                clearInterval(intervalId);
                                i++;
                                setTimeout(nextStep, delay);
                              } else if (retryTotal >= timeout) {
                                clearInterval(intervalId);
                              }
                           }, retryDelay);
                    };
                 }
             nextStep();
};

run(steps, 50, 3000);

この関数は、現在の要素が表示されているかどうかをチェックし続けるために使用する関数をrun()定義します。完了すると、アクションを実行し、間隔をクリアして、を介して自分自身を呼び出すことにより、次の要素に進みます。nextStep()setIntervalsetTimeout

タイムアウトの概念をポーリングに適合させる方法がわかりませんでした。指定された時間が経過しても現在の要素が表示されない場合はどうしますか?次の要素も前の手順に依存する可能性があるため、実際に次の要素に進むことはできません。間隔を空けて再度電話をかけないことで、すべてを中止できると思いますnextStep()編集:最後の文のように機能するようにコードを更新しました。

于 2012-05-15T00:56:02.973 に答える
1

ここに何かがあります。私はそれを徹底的にテストしていません:

var run = function(steps, interval)
{
    var timer,
        time = 0, timeout = 10000,
        ciel = steps.length - 1,
        i = 0;

    run_single(steps[0]);

    function run_single(item)
    {
        timer = setInterval(function()
        {
            var $el = $(item.selector);

            time += interval;

            if ( $el.length )
            {
                clearInterval( timer );
                time = 0;

                $el.trigger( item.action );

                i < ciel && run_single( step[ ++i ] );
            }
            else
            {
                if ( time >= timeout ) clearInterval( timer );
            }

        }, interval);
    }
};

var steps = [
    {action: 'click', selector: '#first'},
    {action: 'hover', selector: '#second'},
    {action: 'change', selector: '#third'}
    // and so on...
];

run(steps, 100);

ここで実際に見てください:http://jsfiddle.net/myaeh/

于 2012-05-15T02:24:19.410 に答える