0

私は、phpプログラムの複数のインスタンスを同じバージョンに更新し続けることができる方法に取り組んでいます。

私のソフトウェアは、最新バージョンに関する情報を含むRSSフィードをチェックします。利用可能なアップデートがあることがわかると、「アップデート」ページへのリンクが表示されます。ユーザーが[更新]リンクをクリックすると、更新が必要な各ファイルを一度に1つずつ更新するjquery関数があります。

$.getJSON('http://softwareserver.com/updateFileList.php?fromver=1.0', function(data) {
    var filesToDo = data.length;

    $.each(data, function(num, file) {
        num = num + 1;
        action = file.charAt(0);
        name = file.substring(1);

        if ( action == "+" )
        {
            $('#upsole').append("<p><strong>Adding</strong> " + name + ". . .</p>");
                $.get("{$var['sbpurl']}/updateAction.php", { action: "add", file: name, revision: "{$TMP['rev']}" } );
        }

        else if ( action == "-" )
        {
            $('#upsole').append("<p><strong>Removing</strong> " + name + ". . .</p>");
                $.get("{$var['sbpurl']}/updateAction.php", { action: "remove", file: name, revision: "{$TMP['rev']}" } );
        }

        else if ( action == "~" )
        {
            $('#upsole').append("<p><strong>Updating</strong> " + name + ". . .</p>");
                $.get("{$var['sbpurl']}/updateAction.php", { action: "update", file: name, revision: "{$TMP['rev']}", version: "{$TMP['ver']}" } );
        }

        var completed = num / filesToDo * 100;

        $('#barcolor').css('width', completed + '%');
        $('#numProgress').html(completed.toFixed(0));

        if ( completed == 100 )
        {
            $('#conutt').html('<a href="index.php" class="button"> Continue > </a>');
            $('#upsole').append("<p><strong>Update Complete</strong></p>");
        }
    });
});

更新中のdivコンテナに各ファイル名を表示します。また、すべてのファイルが更新されるまで各ファイルが更新されると、0から100%まで変化するプログレスバーがあります。しかし、すべてが完了すると、単純に0から100まで変化します。各ファイルが希望どおりに更新されるため、実際には進行状況は表示されません。

プログレスバーは0%から7%、15%など、100%に達するまで続くと思いますが、すべてが完了するまで何も起こりません。先ほど言ったように、0%から100%になります。

$ .eachはこれに最適なソリューションではありませんか?

4

2 に答える 2

1

c0nfus3d1、@ muからの回答があるようですが、大きな中断の前に私が以前に準備し始めたソリューションを見たいと思うかもしれません。

私が見る限り、.each()その仕事には良いことであり、あなたのコードはそれを機能させるために非常に軽い変更を加えるだけで済みます。

ただし、このよりきれいで読みやすいバージョンのようなものを提供するために、さらにmodを使用することでメリットが得られる可能性もあります。

$.getJSON('http://softwareserver.com/updateFileList.php?fromver=1.0', function(data) {
    var filesToDo = data.length;
    var filesDone = 0;
    var activityStr = "<p><strong>%s1</strong>%s2</p>";//activity message template 

    function showProgress() {
        filesDone++;
        var completed = 100 * filesDone / filesToDo;

        $('#barcolor').css('width', completed + '%');
        $('#numProgress').html(completed.toFixed(0));

        if ( filesDone == filesToDo ) {
            $('#conutt').html('<a href="index.php" class="button"> Continue > </a>');
            $('#upsole').append(activityStr.replace('%s1', 'Update Complete').replace('%s2', ''));
        }
    }

    $.each(data, function(num, file) {
        var dataObj = {//data common to all cases below. 
                file: file.substring(1),
                revision: "{$TMP['rev']}" 
            },
            a, d;

        switch (file.charAt(0)) {
            case "+":
                a = 'Adding';
                d = $.extend({action:"add"}, dataObj);
                break;
            case "-":
                a = "Removing";
                d = $.extend({action:"remove"}, dataObj);
                break;
            case "~":
                a = "Updating";
                d = $.extend({action:"update", version:"{$TMP['ver']}"}, dataObj);
        }
        $('#upsole').append(activityStr.replace('%s1', a).replace('%s2', ' ' + d.file + '. . .'));
        $.get("{$var['sbpurl']}/updateAction.php", d).done(showProgress);
    });
});

テストされていません

ノート :

  • switch / case構造は、if / else if / else ifを置き換え、後続の2つの一般化された式をフィードする2つの変数の確立のみに関係します。
  • $.extend()一般オブジェクトとケース固有のオブジェクトをマージして、内部$.getデータを構築するために使用されます。
  • 進行状況メッセージは.replace()、文字列テンプレートに適用することによって生成されます。
  • この関数showProgress()は、各内部.get()呼び出しの完了に応答して呼び出されます。
  • 内部.get()リクエストは非常にすばやく連続して発行されますが、レスポンスはサーバーから戻ってきたときに、そしてどのような順序でも処理されます。

多分これはあなたが使うことができるいくつかのアイデアを含んでいます。

于 2013-01-06T00:54:48.843 に答える
1

いいえ、$.eachこの仕事に適したツールではありません。主な問題は、ブラウザのJavaScriptがシングルスレッドであるため、すべてのDOMが更新されることです。

  • $('#upsole').append(...)
  • $('#barcolor').css(...)
  • $('#numProgress').html(...)

ブラウザが制御を取り戻したときに処理されるようにキューに入れられます。では、ブラウザはいつ制御を取り戻すのでしょうか。$.eachもちろん終了後。結果が表示されます。ユーザーは、物事が何もない状態から1つのステップで終了することを確認します。$.getまた、考慮すべき非同期の性質もあります。

DOMを更新するたびに、制御をブラウザに戻す必要があります。たくさんの$.get呼び出しがあるので、それらの成功コールバックを使用して、DOMの変更をそれらの変更に対するブラウザーの応答とインターリーブできます。このようなもの:

$.getJSON('http://softwareserver.com/updateFileList.php?fromver=1.0', function(data) {
    var filesToDo = data.length;
    var next_one  = function() {
        var file = data.shift();
        if(!file) {
            // If `data` is empty then we're all done so we can put the UI into
            // the "update complete" state and end the process by not calling
            // next_one() again.
            $('#conutt').html('<a href="index.php" class="button"> Continue &gt; </a>');
            $('#upsole').append("<p><strong>Update Complete</strong></p>");
            return; 
        }

        // Set up the next iteration by parsing `file`. We put the `$.get` stuff
        // into an object so that we only have one `$.get` call; the reason for
        // this will be clear shortly.
        var action = file.charAt(0);
        var name   = file.substring(1);
        var get    = { };
        if(action == '+') {
            get = {
                msg:    '<p><strong>Adding</strong> ' + name + '...</p>',
                url:    "{$var['sbpurl']}/updateAction.php",
                params: { action: "add", file: name, revision: "{$TMP['rev']}" }   
            };
        }
        else if(action == '-') {
            //...
        }
        else if(action == '~') {
            //...
        }

        // Tell them what we're about to do...
        $('#upsole').append(get.msg);

        // This `$.get` call is asynchronous so the browser will get control here 
        // and any pending DOM updates will be applied.
        $.get(get.url, get.params, function() {
            // Update the DOM with the latest status.
            var completed = (filesToDo - data.length) / filesToDo * 100;
            $('#barcolor').css('width', completed + '%'); 
            $('#numProgress').html(completed.toFixed(0));

            // And trigger the next iteration.
            next_one();
        });
    };

    // Crank it up.
    next_one();
});

基本的な考え方は、data空になるまで反復することです。反復するたびにの最初の要素が削除されるため、いつ戻るかを確認することで、の終わり(および反復の終わり)をdata検出できます(これは誤りです)。反復ごとにがトリガーされ、ブラウザに制御が返され、DOMを更新できるようになります。その後、コールバックは次の反復をトリガーします。dataundefined$.get$.get

エラー処理などの優れた点は、読者の練習問題として残されています。

于 2013-01-05T22:42:26.217 に答える