Javascript 如何等待ajax请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27612372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:23:29  来源:igfitidea点击:

How to await the ajax request?

javascriptphpjqueryajax

提问by masm64

I am trying to write a JS code that will cancel the "btn_submit" buttons .onclick event if the given number already exists in the database. I use AJAX to query the DB for the given number and to determine if the should send the data to a .php site which will upload the question. To determine this I need the numOfRows variable's value, but because I set it in AJAX it will stay on 0. The validation() function will finish before my AJAX query finishes and this causes the problem that will always state that the given number does not exist in the DB (numOfRows will always stay on 0). How can I await the AJAX query's finish before I compare the numOfRows to 0 in my validation() function's ending lines? If the number already exists in the DB, I need to return false to this line:

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

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

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

Thank you!

谢谢!

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);               
        }
    });
}

采纳答案by Murtaza Hussain

use of async/awaitwith a transpilers like Babel to get it working in older browsers. You'll also have to install this Babel preset and polyfill from npm: npm i -D babel-preset-env babel-polyfill.

使用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();

or the .thencallback is just another way to write the same logic.

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

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

回答by Terry

Using async: falseis an extremely bad idea, and defeats the whole purpose of using AJAX at the first place — AJAX is meant to be asynchronous. If you want to wait for a response from your script when you make the AJAX call, simply use deferred objects and promises:

使用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);

I see in your code that you are using a mixture of both native JS and jQuery — it helps if you stick to one :)

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

回答by developerwjk

(I acknowledge this is not the best way to go about things, but this is the quickest way to get your code working as is. Really though, you should rethink how you are pulling the numOfRows value so that it will work with truly asynchronous Ajax. All that being said...):

(我承认这不是处理事情的最佳方式,但这是让您的代码按原样工作的最快方式。实际上,您应该重新考虑如何提取 numOfRows 值,以便它可以与真正的异步 Ajax 一起使用. 说了这么多...):

Start by setting async : falsein the $.ajaxcall. The A in Ajax stands for asynchronous. That means, execution continues rather than waiting for it to return. You want to turn that off (i.e. make it synchronous). Actually, that should be the whole solution given the code you have there.

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

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

One caveat from the docs for $.ajax:

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

Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().

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