JavaScript 同步 Ajax 请求特性

标签 javascript jquery ajax multithreading synchronization

如果我以“奇怪”的方式做事,我想在序言中表达歉意,因为我主要是一名 C 开发人员,并且正在像使用 C 语言一样解决这个 AJAX 问题。

我有一个脚本将连接到“推送服务器”,该脚本会等待消息可用,然后仅发送该消息并中断连接。然后客户端必须重新建立连接以监听 future 的消息。

我尝试通过在异步回调中实现同步 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中。如果没有更多消息,我将退出循环,结束异步线程并完成任务。

问题在于,一旦收到所有消息,DOM 访问似乎就全部合并了。即,仅在收到所有消息并且异步线程退出后才会发生追加。

注释掉的警报是一个测试 - 它完美工作。我在每次通知后都会收到一个消息框,并且它会正确暂停,直到下一条消息(其余代码按原样)。

我猜这是我的浏览器(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 没有信号原语?

最佳答案

弄清楚了这一点 - 我不知道为什么我之前没有看到这一点,但我的后一个代码片段工作得很好。我在发布时没有意识到这一点,但它不能溢出堆栈,因为每次运行它都会启动异步调用并退出 - 因此堆栈帧的深度永远不会超过 2 或 3。异步调用由外部管理,不会在堆栈上,因此每次都会重新开始。

我仍然希望了解为什么第一个方法(异步调用中的同步代码)不起作用/不起作用的任何意见。

关于JavaScript 同步 Ajax 请求特性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9901060/

相关文章:

python - 使用 Django 提供动态生成的图像

ajax - C# 中服务器端代码的 ModalPopupExtender

javascript - 添加功能的笨拙实现

javascript - JQuery 获取行数

javascript - 减少 A 到 Z 字母组的函数数量

jquery - 如何在div中打洞?

javascript - 如何访问外部 javascript 变量并在 xsl 中打印它?

javascript - 从 EasyUi 选项卡隐藏面板

javascript - 观察到在背景中最大化图像滚动?

javascript - 如何使用jquery在数据库中创建表