我有多个需要串行调用的进程(我正在使用同步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运行3Done 3Done 3Done 3
我想得到
运行1Done 1运行2Done 2运行3Done 3
如果我在updateStatus函数中插入alert()语句,那么我会得到我想要的响应/执行顺序。浏览器是否为3个函数调用创建3个线程并异步执行它们?
如何连续运行? setTimeout是否正确实现?感谢您的帮助。
答案 0 :(得分:2)
听起来你想要排队AJAX调用。 jQuery提供了一个很好的队列函数,因此您可以确保一个接一个地调用一系列函数。 Mootools和其他框架提供类似的功能。
以下是我的 fiddle 中的代码,其中显示了如何执行此操作。
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
答案 1 :(得分:0)
您在浏览器中必须了解的有关Javascript的一点是它是单线程的。当您更改DOM时,屏幕不会更改,直到您的脚本放弃控制权为止。
以下是两次调用doWork()时的实际事件序列:
doWork()
doWork()
添加了正在运行的消息updateStatus()
的调用排队以稍后执行doWork()
doWork()
添加了正在运行的消息updateStatus()
的调用排队以稍后执行runProcess()
退出并将控制权返回给浏览器updateStatus()
来电。完成后,屏幕会更新updateStatus()
来电。完成后,屏幕会更新您可以根本不弄乱updateStatus()
来电,从而获得您想要的内容,并在doWork()
内打印完成的消息。
答案 2 :(得分: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(" " + oResult.Message);
if (!oResult.Success) {
$("#<%:this.FailureText.ClientID %>").append(" " + oResult.Error);
} else { next(); }
},
error: function (exc) {
$("#Message").append(" " + 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>