【问题标题】:How to await the ajax request?如何等待ajax请求?
【发布时间】:2015-02-21 02:58:25
【问题描述】:

我正在尝试编写一个 JS 代码,如果数据库中已经存在给定的数字,它将取消“btn_submit”按钮 .onclick 事件。我使用 AJAX 查询给定数字的数据库,并确定是否应该将数据发送到将上传问题的 .php 站点。为了确定这一点,我需要 numOfRows 变量的值,但是因为我在 AJAX 中设置它,所以它会保持为 0。validation() 函数将在我的 AJAX 查询完成之前完成,这会导致问题总是指出给定的数字不存在于数据库中(numOfRows 将始终保持为 0)。 在我将验证()函数的结尾行中的 numOfRows 与 0 进行比较之前,如何等待 AJAX 查询完成?如果数据库中已经存在该数字,我需要在这一行返回 false:

document.getElementById("btn_submit").onclick = 验证;

谢谢!

var textAreaList;
var numOfRows = 0;
var finished = false;

document.getElementById("btn_submit").onclick = validation;

textAreaList = document.getElementsByClassName("text_input");

function validation() {
    loadNumRows();

    try {
        document.getElementById('failure').hidden = true;
    }
     catch(e) {
         console.log(e.message);
     }
    textAreaList = document.getElementsByClassName("text_input");
    var failValidation = false;
    for (var i = 0; i < textAreaList.length; i++) {
        console.log(textAreaList[i]);
        if (textAreaList[i].value == "") {
            textAreaList[i].style.border = "2px solid #ff0000";
            failValidation = true;
        } else {
            textAreaList[i].style.border = "2px solid #286C2B";
        }
    }

    return !(failValidation || numOfRows != 0);
}

function loadNumRows(){
    $.ajax({
        url: 'php/SeeIfNumberExists?number=' + document.getElementById('number_inp').value,
        type: "GET",
        cache: false,
        success: function (html) {
           numOfRows = parseInt(html);               
        }
    });
}

【问题讨论】:

标签: javascript php jquery ajax


【解决方案1】:

(我承认这不是处理事情的最佳方式,但这是让您的代码按原样运行的最快方式。实际上,您应该重新考虑如何拉取 numOfRows 值,以便它将与真正的异步 Ajax 一起工作。话虽如此...):

首先在$.ajax 调用中设置async : false。 Ajax 中的 A 代表 异步。这意味着,执行继续而不是等待它返回。您想将其关闭(即使其同步)。实际上,考虑到您那里的代码,这应该是整个解决方案。

$.ajax({
        url: 'php/SeeIfNumberExists?number=' + document.getElementById('number_inp').value,
        type: "GET",
        async: false,
        cache: false,
        success: function (html) {
           numOfRows = parseInt(html);               
        }
    });

$.ajax 的文档中的一个警告:

跨域请求和dataType:“jsonp”请求不支持同步操作。请注意,同步请求可能会暂时锁定浏览器,从而在请求处于活动状态时禁用任何操作。从 jQuery 1.8 开始,不推荐在 jqXHR ($.Deferred) 中使用 async: false ;您必须使用成功/错误/完成回调选项,而不是 jqXHR 对象的相应方法,例如 jqXHR.done() 或已弃用的 jqXHR.success()。

【讨论】:

    【解决方案2】:

    使用async: false 是一个非常糟糕的主意,并且一开始就违背了使用 AJAX 的全部目的——AJAX 本来就是异步的。如果您想在进行 AJAX 调用时等待脚本的响应,只需使用延迟对象和承诺:

    var validation = function () {
        var numberCheck = $.ajax({
            url: 'php/SeeIfNumberExists?number=' + $('#number_inp').val(),
            type: "GET"
        });
    
        // Listen to AJAX completion
        numberCheck.done(function(html) {
            var numOfRows = parseInt(html),
                textAreaList = $('.text_input'),
                finished = false;
    
            // Rest of your code starts here
            try {
                document.getElementById('failure').hidden = true;
            }
            catch(e) {
                console.log(e.message);
            }
    
            // ... and the rest
        });
    
    }
    
    // Bind events using jQuery
    $('#btn_submit').click(validation);
    

    我在您的代码中看到您正在使用原生 JS 和 jQuery 的混合体——如果您坚持使用其中一个会有所帮助:)

    【讨论】:

    • 将 ajax 请求存储在变量中并使用 .done 而不是仅仅给它一个 successerror 方法有什么好处吗?
    • @developerwjk 从 v1.8 开始,jqXHR.success() 方法已被正式弃用。请改用jqXHR.done(),因为$.ajax()promises natively implemented,当从服务器接收到响应时,它将返回一个已解析的延迟对象。已解决的对象将映射到.done(),而被拒绝的对象将映射到.fail()。不过,两者都将映射到.always()
    【解决方案3】:

    async/await 与 Babel 之类的转译器一起使用,以使其在旧版浏览器中运行。你还必须从 npm 安装这个 Babel 预设和 polyfill:npm i -D babel-preset-env babel-polyfill。

    function getData(ajaxurl) { 
      return $.ajax({
        url: ajaxurl,
        type: 'GET',
      });
    };
    
    async function test() {
      try {
        const res = await getData('https://api.icndb.com/jokes/random')
        console.log(res)
      } catch(err) {
        console.log(err);
      }
    }
    
    test();
    

    .then 回调只是编写相同逻辑的另一种方式。

    getData(ajaxurl).then(function(res) {
        console.log(res)
    }
    

    【讨论】:

    • 注意:babel-polyfill 不再需要,使用最新的 CRA..
    【解决方案4】:

    永远不要使用async:false,这很危险,您的应用可能会出现问题。

    只有当你的响应返回一个承诺时,你才能使用 await。

    不幸的是,jQuery ajax 在完成时没有返回 Promise。

    但是你可以在 ajax 请求中使用 Promise 并在完成后返回 Promise。

    function asyncAjax(url){
        return new Promise(function(resolve, reject) {
                $.ajax({
                    url: url,
                    type: "GET",
                    dataType: "json",
                    beforeSend: function() {            
                    },
                    success: function(data) {
                        resolve(data) // Resolve promise and when success
                    },
                    error: function(err) {
                        reject(err) // Reject the promise and go to catch()
                    }
                });
        });
    }
    

    我们已经将 ajax 调用转换为 Promise,所以现在我们可以使用 await。

    try{
        const result = await asyncAjax('your url');
    } catch(e){
        console.log(e);
    }
    

    【讨论】:

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