【问题标题】:Ajax Request waiting another ajax request to be executedAjax 请求等待另一个 ajax 请求被执行
【发布时间】:2018-01-11 01:36:21
【问题描述】:

我正在用 PhP 开发一个聊天,我正在做长轮询以检查服务器上的新消息。在执行长轮询的 Ajax 请求中,服务器最多检查 25 秒是否有新的注册消息。在服务器到达时,它不会向 javascript 返回任何内容,如果我发送新请求,浏览器会等待检查完成发送新消息

chat.js

function sndmessage(message, idchat) {

    if (message != "") {

        var $this = $('.chat .msgs');
        var indice = 0;
        var msg = message;

        $('#sendmsg').val("");

        $.ajax({
            url: "../ajax/sendmessage.ajax.php",
            type: "POST",
            data: {
                "message": msg,
                "id": id
            },
            success: function(response) {
                return;
            }
        });
    }

    return true;
}


function polling(idm, idu) {
    var interval;

    $.ajax({
        async: true,
        url: "../ajax/polling.ajax.php",
        data: {
            "idm": idm,
            "idu": idu
        },
        type: "POST",
        dataType: "JSON",
        success: function(response) {
            clearInterval(interval);

            if (response.response == false) {
                interval = setTimeout(function() {
                    polling(idm, idu);
                }, 500);
            } else {
                if ('id' in response[0][0]) {

                    for (var i = 0; i < response[0].length; i++) {

                        if (mensagensIDs.indexOf(response[0][i]['id']) < 0) {
                            mensagensIDs.push(response[0][i]['id']);

                            let data = response[0][i]['data'].split(" "),
                            dia = data[0].split("-").reverse().join().replaceAll(",", "/"),
                            hora = data[1].split(":").slice(0, 2).join(":"),
                            mensagem = response[0][i]['mensagem'],
                            remetente = (response[0][i]['remetente'].indexOf(" - ") > 0) ? "admin" : "usuario",
                            destinatario = (response[0][i]['destinatario'].indexOf(" - ") > 0) ? "admin" : "usuario",
                            id = response[0][i]['id'];

                            let d = new Date();

                            let html = (d.getDate() == dia.split("/")[0]) ? hora : dia + " - " + hora;

                            chats.push({
                                "idu": idu,
                                "chat": {
                                    "id": id,
                                    "class": (remetente == "admin") ? "msg-adm teal lighten-1" : "msg-eu",
                                    "class2": (remetente == "admin") ? "white-text" : "blue-text text-darken-2",
                                    "msg": mensagem,
                                    "tooltip": html,
                                    "tooltippos": (remetente == "admin") ? "right" : "left"
                                }
                            });

                            if (idu == chatatual) {

                                $('.chat .msgs').append('<div id="' + idu + '" class="col s12">\
                                <div class="' + ((remetente == "admin") ? "msg-adm teal lighten-1" : "msg-eu") + ' z-depth-1">\
                                <span class="tooltipped pointer ' + ((remetente == "admin") ? "white-text" : "blue-text text-darken-2") + '" data-position="' + ((remetente == "admin") ? "right" : "left") + '" data-delay="50" data-tooltip="' + html + '">' + mensagem + '</span>\
                                </div>\
                                </div>').animate({
                                    scrollTop: $('.msgs').prop("scrollHeight")
                                }, 500);

                            } else {
                                $('li.collection-item.avatar#' + idu).find('.badge').text("New message");

                            }
                        }

                    }

                    interval = setTimeout(function() {
                        polling(mensagensIDs[mensagensIDs.length - 1], idu);
                    }, 500);

                } else {
                    interval = setTimeout(function() {
                        polling(idm, idu);
                    }, 5000);
                }
            }
        }
    });

}

我想知道如何在不等待其他请求的情况下发送请求

【问题讨论】:

标签: javascript php jquery ajax


【解决方案1】:

其实很简单。您正在做的是发送请求并在收到响应时调用下一个循环,这不是您想要的。你应该做的是:

function polling(idm,idu){
    var interval;
    $.ajax({/*do your stuff here*/});
    setTimeout(function(){pooling(/*whatever*/)}, 500); // See that this is outside the ajax call, so it doesn't wait for the response
}

【讨论】:

    【解决方案2】:

    为什么不将 ajax 中的两个“异步”都设置为 true?您可以发送第二个 ajax 而无需等待第一个。

    $.ajax({
             'async': true,
             //your code
          })
    

    【讨论】:

    • function sndmessage(message, idchat) { if (message != "") { var $this = $('.chat .msgs');变量索引 = 0; var msg = 消息; $('#sendmsg').val(""); $.ajax({ async: true, url: "../ajax/sendmessage.ajax.php", type: "POST", data: { "message": msg, "id": id }, 成功: function(响应){返回;}}); } 返回真; }
    • async: true 是默认值(无论如何,sync: true 在浏览器中已被弃用);指定它是不必要的。
    【解决方案3】:

    在您知道如何使用 promises 之前,这种事情可能是一场彻头彻尾的噩梦。

    这里的关键是要理解:

    • jQuery.ajax() 返回一个承诺。
    • 您寻求的超时是通过将jQuery.ajax() 返回的承诺与保证在 25000 毫秒后拒绝的承诺进行竞争来实现的。

    现在,有两种编写代码的方法(解释见脚注2)

    始终使用 jQuery 承诺

    前两个实用函数:

    // a promise-returning `delay()` utility, which is the only place that `setTimeout()` is used.
    function delay(t) {
        return new jQuery.Deferred(function(dfrd) {
            setTimeout(dfrd.resolve, t);
        }).promise();
    }
    
    // a promise-returning `race()` utility which ensures that the first promise in `promises` to resolve/reject will resolve/reject the returned promise.
    function race(promises) {
        return new jQuery.Deferred(function(dfrd) {
            promises.forEach(function(p) {
                p.then(function(result) {
                    dfrd.resolve(result);
                }, function(reason) {
                    dfrd.reject(reason);
                });
            });
        }).promise();
    }
    

    现在,polling()

    function polling(idm, idu) {
        // first promise
        var ajaxPromise = $.ajax({
            'async': true,
            'url': '../ajax/polling.ajax.php',
            'data': { 'idm': idm, 'idu': idu },
            'type': 'POST',
            'dataType': 'JSON',
        }).then(function(response) {
            if (response.response && ('id' in response[0][0])) {
                // ... lots of synchronous processing ...
                return [mensagensIDs[mensagensIDs.length - 1], idu]; // or maybe `return [mensagensIDs.pop(), idu]`?
            } else {
                return [idm, idu];
            }
        });
    
        // second promise
        var timeoutPromise = delay(25000).then(function() {
            return new jQuery.Deferred().reject(new Error('long-poll-timeout')).promise();
        });
    
        // Now the clever bit ...
        // At this point you have two promises, which can be raced against each other.
        // Exactly what happens next, depends on who wins the race.
        // * if `timeoutPromise` wins the race, it will be caught below, the ajax will be aborted, then execution will progress to the second chained `.then()`.
        // * if `ajaxPromise` wins the race, then the `.catch()` clause will be bypassed, and execution will progress directly to the second chained `.then()`.
        return race([ajaxPromise, timeoutPromise])
        .then(null, function(error) { // this is effectively a `.catch()` block.
            console.log(error.message); // you will see 'long-poll-timeout' (or possibly some ajax/http error message).
            ajaxPromise.abort(); // ensure that `ajaxPromise` **doesn't** follow its success path.
            return [idm, idu]; // deliver `[idm, idu]` to the chained .then().
        })
        .then(function(args) { // via one route or other, `[idm, idu]` or `[mensagensIDs[mensagensIDs.length - 1], idu]` is delivered here as `args`.
            return delay(500).then(function() {
                return polling.apply(null, args);
            });
        });
    }
    

    使用 jQuery.ajax() 和 javascript 原生 Promises

    首先,一个效用函数:

    // a promise-returning `delay()` utility, which is the only place that `setTimeout()` is used.
    function delay(t) {
        return new Promise(function(resolve, reject) {
            setTimeout(resolve, t);
        });
    }
    

    现在,polling()

    function polling(idm, idu) {
        // first promise
        var ajaxPromise = $.ajax({
            'async': true,
            'url': '../ajax/polling.ajax.php',
            'data': { 'idm': idm, 'idu': idu },
            'type': 'POST',
            'dataType': 'JSON',
        }).then(function(response) {
            if (response.response && ('id' in response[0][0])) {
                // ... lots of synchronous processing ...
                return [mensagensIDs[mensagensIDs.length - 1], idu]; // or maybe `return [mensagensIDs.pop(), idu]`?
            } else {
                return [idm, idu];
            }
        });
    
        // second promise
        var timeoutPromise = delay(25000).then(function() {
            return Promise.reject(new Error('long-poll-timeout'));
        });
    
        // Now the clever bit ...
        // At this point you have two promises, which can be raced against each other.
        // Exactly what happens next, depends on who wins the race.
        // * if `timeoutPromise` wins the race, it will be caught below, the ajax will be aborted, then execution will progress to the chained `.then()`.
        // * if `ajaxPromise` wins the race, then the `.catch()` clause will be bypassed, and execution will progress directly to the chained `.then()`.
        return Promise.race([ajaxPromise, timeoutPromise])
        .catch(function(error) {
            console.log(error.message); // you will see 'long-poll-timeout' (or possibly some ajax/http error message).
            ajaxPromise.abort(); // ensure that `ajaxPromise` **doesn't** follow its success path.
            return [idm, idu]; // deliver `[idm, idu]` to the chained .then().
        })
        .then(function(args) { // via one route or other, `[idm, idu]` or `[mensagensIDs[mensagensIDs.length - 1], idu]` is delivered here as `args`.
            return delay(500).then(function() {
                return polling.apply(null, args);
            });
        });
    }
    

    注意事项:

    1. 详细解释见代码中的 cmets
    2. 使用 jQuery.ajax 的 timeout: 选项更简单,但 Firefox 3.0+ 中的限制使这种方法不通用。
    3. 没有任何版本的 IE(据报道)包含原生 Promise。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-09
      • 2018-08-05
      • 1970-01-01
      • 2015-02-21
      • 2014-04-24
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多