4

連続して呼び出す必要がある複数のプロセスがあります (同期 AJAX 呼び出しを使用しています)。長時間実行されているプロセスの完了後にステータスを表示し、次のプロセスに進みたいと思います。ここに私が書いたサンプルコードがあります。

    var counter = 0;
function runProcess(input, output) {
    doWork();
    doWork();
    doWork();
};
function doWork() {
    counter++;
    document.getElementById('<%=this.progressMonitor.ClientID%>').innerHTML += "Running " + counter;

    // some lengthy calculations
    for (var i = 0; i < 1000000; i++) {
        var foo = Math.random();
    }
    setTimeout(updateStatus, 1000);
};
function updateStatus() {
    document.getElementById('<%=this.progressMonitor.ClientID%>').innerHTML += "Done " + counter;
}

これを実行すると、次の応答が返されます。

実行中 1実行中 2実行中 3完了 3完了 3完了 3

私は取得したいです

実行中 1完了 1実行中 2完了 2実行中 3完了 3

updateStatus 関数に alert() ステートメントを挿入すると、必要な応答/実行順序が得られます。ブラウザは 3 つの関数呼び出しに対して 3 つのスレッドを作成し、それらを非同期で実行していますか?

これを連続して実行するにはどうすればよいですか?setTimeout は正しく実装されていますか? 事前にご協力いただきありがとうございます。

4

3 に答える 3

2

AJAX 呼び出しをキューに入れたいようです。jQuery は優れたキュー機能を提供するため、一連の関数が次々と呼び出されるようにすることができます。Mootools やその他のフレームワークも同様の機能を提供します。

これは、その方法を示す私のフィドルのコードです。

var queueElement = $("#output");
var counter = 0;

function doWork(next) {
    queueElement.append("Starting " + counter + "<br/>");
    counter++;
    $.ajax('/echo/json/').always(function() {
        queueElement.append("Ending " + counter + "<br/>");
        next();
    });
}

queueElement.queue('workQueue', doWork);
queueElement.queue('workQueue', doWork);
queueElement.queue('workQueue', doWork);
queueElement.dequeue('workQueue'); // start the work queue
于 2012-11-11T01:11:02.810 に答える
0

キューはうまく機能します。連続して呼び出す必要のある$.ajaxメソッドでキューを使用するとうまくいきます。キューを使用せずに「async:false」オプションを使用した場合、UIは、長時間実行されているすべてのプロセスが完了した後にのみ更新されます。

私を正しい方向に向けてくれてありがとう!誰かが探している場合の私の最終的なコードは次のとおりです。

function callService(url, workflowid, modelid, next) {
        var jData = {};
        jData.workflowid = workflowid;
        jData.modelid = modelid;
        //alert(JSON.stringify(jData));
        $.ajax({
            url: url,
            type: "POST",
            dataType: "json",
            contentType: "application/json; charset=utf-8;",
            async: true,
            cache: false,
            data: JSON.stringify(jData),
            success: function (oResult) {
                $("#Message").append("&nbsp;&nbsp;" + oResult.Message);
                if (!oResult.Success) {
                    $("#<%:this.FailureText.ClientID %>").append("&nbsp;&nbsp;" + oResult.Error);
                } else { next(); }
            },
            error: function (exc) {
                $("#Message").append("&nbsp;&nbsp;" + exc.responseText);
            }
        });
    }
    function runServices() {
        var queueElement = $("#q");
        var queueStatus = $("#Message");

        queueStatus.append("<br/>Starting workflows at : " + new Date() + "<br/>");
        var list = $(":input:checkbox:checked"); // getting all selected checkboxes.
        $(list.each(function () {
            var workflowid = $(this).val();
            queueElement.queue("WorkflowQ", function (next) {
                callService("/Services/Workflow.svc/rest/runworkflow", workflowid, document.getElementById('<%=this.MODELID.ClientID%>').value, next);
            });
        }));          
        queueElement.dequeue("WorkflowQ");
    };

    <input type="button" id="ExecuteButton" value="Execute Workflow" class="button" onclick="runServices();"/>

<div id="Message"></div>
<div id="q"></div>
于 2012-11-12T19:14:49.347 に答える
0

ブラウザの Javascript について理解しなければならないことの 1 つは、それがシングルスレッドであることです。DOM を変更しても、スクリプトが制御を放棄するまで画面は変わりません。

doWork() を 2 回呼び出した場合の実際のイベント シーケンスは次のとおりです。

  1. 電話doWork()
  2. doWork()実行中のメッセージを追加します
  3. 呼び出しをキューに入れ、updateStatus()後で実行する
  4. doWork()もう一度電話する
  5. doWork()実行中のメッセージを追加します
  6. 呼び出しをキューに入れ、updateStatus()後で実行する
  7. runProcess()終了し、制御をブラウザに戻します
  8. ブラウザは実行中のメッセージで画面を更新します
  9. 最初のupdateStatus()呼び出しが行われます。終了後、画面が更新されます
  10. 2 番目のupdateStatus()呼び出しが行われます。終了後、画面が更新されます

呼び出しをまったくいじらずにupdateStatus()、完了したメッセージを内部から出力するだけで、必要なものを取得できますdoWork()

于 2012-11-09T21:52:27.493 に答える