1

もう 1 つは単純なはずですが、問題を引き起こしています。再帰関数が完全に終了するまで特定のアクションを遅らせるために、jQuery の .Deferred() および .promise() 機能について学習しようとしています。現在、私のコードは次のようになっています。

    function showText(setTarget, setMessage, setIndex, setInterval) {
        var defer = jQuery.Deferred();
        var doShowText = function (target, message, index, interval) {
            if (index < message.length) {
                $(target).append(message[index++]);
                setTimeout(function () { doShowText(target, message, index, interval); }, interval);
            }
            else {
                alert("Done!");
                defer.resolve();
            }
        };

        doShowText(setTarget, setMessage, setIndex, setInterval);
        return defer.promise();
    }

function startButtonClick() {
    displayElement($("#getElement"));
    showText($("#getElement > h1"), "This text will slowly write to the screen.", 0, 50).promise()
        .then(alert("Finished."));

}

これが実行されると、再帰スクリプトの最初の実行後に「終了」アラート(私は延期しようとしています)が実行されるため、(意図した結果ではなく)1文字だけが印刷されたときに表示されます。ただし、すべての文字が印刷されて再帰が完了すると、「完了」アラートが正しく表示されるため、それまで遅延変数を解決しないように思われます。ここで「終了」アラートが早期に呼び出されている理由を誰かが発見するのを手伝ってくれますか? どんな支援も大歓迎です!

編集: コードの少し古いバージョンを誤って投稿してしまったことに気付きました。正しいバージョンに更新されています (実行時の動作は同じです)。

4

3 に答える 3

2

関数では、 の結果startButtonClickを呼び出す必要はありません。これは、 の内部で既に実行しているためです。次に、コールバックへの引数は関数である必要があります。現在、アラート関数を関数として渡すのではなく、すぐに呼び出しています。これがすぐに表示される理由です。関数でラップするだけです。.promise()showTextshowTextthen

function(){ alert("Finished."); }

コードを含む jsfiddle は次のとおりです: http://jsfiddle.net/RnLXF/

于 2013-10-24T02:01:44.470 に答える
2

alertこれは、関数参照を渡すのではなく、実際に関数をすぐに実行しているためです。

代わりにこれを行います:

.then(alert.bind(null, 'finished'));

または

.then(function () {
    alert('finished');
});
于 2013-10-24T02:02:28.230 に答える
1

これは、すべてが素敵な小さなオブジェクトにまとめられたフィドルです: http://jsfiddle.net/YVZKw/3/

plalxとctcherryが既に述べたように、最大​​の問題は .then 呼び出しに関数がないことでした。

HTML

<a href='javascript:void(0)'>Start</a>

<div id='sampleElement'>
    <h1></h1>
</div>

JavaScript

$('a').on('click', function(){

    new ShowText(
        $("#sampleElement > h1"), 
        "I will slowly write text to the screen.",
        50
    )
    .done(function(){
        alert("Finished.")
    });
});

function ShowText(target, message, speed)
{
    me = this;
    me.target = target;
    me.message = message;
    me.index = 0;
    me.speed = speed;
    me.defer = new $.Deferred();

    me.interval = setInterval(function() {
        me.target.append(me.message[me.index++]);
        if (me.index > me.message.length) {
            clearInterval(me.interval);
            me.defer.resolve();
        }
    }, me.speed);

    return me.defer;
}
于 2013-10-24T02:20:11.620 に答える