如果我以“怪异”的方式做事,我想以道歉为前言,因为我主要是一名C开发人员,正如我在C中那样解决这个AJAX问题。
我有一个脚本将连接到“推送服务器”,等待消息可用,然后只发送一条消息并断开连接。然后,客户端必须重新建立连接以侦听将来的消息。
我尝试通过在异步回调中实现同步 AJAX调用来实现这一点,除了它出现在DOM之外它可以工作(也许?我在表现出我的无知这里的JS将阻止,直到所有调用完成。
我不知道如何使用纯粹的异步调用来完成它,因为我不希望每次都通过回调调用回调来耗尽堆栈。
这是代码:
$.ajax({
url: './recoverDevice',
data: JSON.stringify(requestData),
dataType: 'json',
type: 'POST',
success: function(j)
{
console.log(j);
if (j.success)
{
//Indefinitely listen for push messages from the server
var loopMore = true;
while(loopMore)
{
$.ajax({
async: false,
url: './getPendingMessage',
dataType: 'json',
type: 'POST',
success: function(j)
{
//alert(j.message);
$("#progressBox").append("<li>" + j.message + "</li>");
loopMore = !j.complete;
}
});
}
}
else
{
$("#errorBox").show();
$("#errorBox").text(j.errorMessage);
}
}
});
现在,从逻辑上讲,此代码应工作。在异步函数中,我循环遍历同步 JS调用,每次收到消息时我都会将其附加到DOM,并且只有当服务器告诉我将会我不再发出消息退出循环,结束异步线程并完成任务。
问题是,一旦收到所有消息,DOM访问似乎全部合并。即只有在收到所有消息且异步线程退出后才会发生追加。
注释掉的alert
是一个测试 - 它完全 。我在每个通知后都会收到一个消息框,它会正确暂停,直到下一条消息(其余代码为原样)。
我猜这是我的浏览器(Chrome)通过在异步线程退出之前不允许DOM操作来做一些魔法来防止竞争条件?还是我离开了标记并在这里咆哮错误的树?
摆脱循环并将async
设置为true会使第一条消息正确接收(没有问题),但显然此后没有消息。
显然我可以这样做:
function GetMessage()
{
$.ajax({
async: true,
url: './getPendingMessage',
dataType: 'json',
type: 'POST',
success: function(j)
{
$("#progressBox").append("<li>" + j.message + "</li>");
if (!j.complete)
{
GetMessage();
}
}
});
}
但是这会导致堆栈随着时间的推移而溢出(没有?)。
一个明显的解决方案是在这里也使用异步调用,但是通过某种同步原语发出while循环信号暂停并继续新调用,但看起来JS没有信令原语?
答案 0 :(得分:0)
想出这个 - 我不知道为什么我之前没有看到这个,但我的后一个代码片段完美无缺。在发布时我没有意识到它,但它不会溢出堆栈,因为每次运行它都会启动异步调用并退出 - 所以堆栈帧永远不会超过2或3深。异步调用是在外部管理的,不会在堆栈中,因此每次重新启动时都会。
我仍然感谢为什么第一种方法(异步调用中的同步代码)没有/不会工作的任何输入。