等待AJAX​​呼叫无法正常工作

时间:2019-10-22 12:06:09

标签: ajax async-await

我具有以下两个功能:

function scan_request(address, file_url) {
    $.ajax({
        type: "POST",
        async: true,
        crossDomain: true,
        url: 'http://some_site/api/file/scan',       
        dataType: "text",
        success: function (data, textStatus, jqXHR) {
            var json = $.parseJSON(data);//get json response and parse it
            $(json).each(function (i, val) {//extract data from json
                $.each(val, async function (key, value) {
                    if (key.toLowerCase() == "jobid") {
                        var result = await query_request();
                        alert("result:" + result);
                    }
                });
            });
        }
    });
}

async function query_request() {
    var settings = {
        "async": true,
        "crossDomain": true,
        "url": 'http://some_site/api/file/query',
        "method": "POST"
    }
    var res;
    $.ajax(settings).then(function (response) {
        alert("response: " + response);
        res = response;
    });
    return res;
}

它首先提醒result: undefined

及其发出警报后:response: [object Object]

但是我期望:

第一警报response: [object Object]

并且在警报result: [object Object]

之后

似乎没有等待呼叫:var result = await query_request();,因此结果是不确定的,并且警报出现在内部警报之前,我想念什么?

1 个答案:

答案 0 :(得分:1)

您只能await个承诺。 (或返回承诺的函数。)

您的query_request()应该返回由$.ajax()创建的诺言。而且,由于它不需要等待任何自身,因此不需要将其标记为async

// returns a promise, i.e. can be awaited in caller
function query_request(value) {
    return $.ajax({
        crossDomain: true,
        url: 'http://some_site/api/file/query',
        method: "POST",
        data: {jobid: value}
    });
}

现在,您可以在await函数中query_request()的结果async

$(json).each(function (i, val) {
    $.each(val, async function (key, value) {
        if (key.toLowerCase() == "jobid") {
            var result = await query_request(value);
            alert("result:" + result);
        }
    });
});

但是,此代码有一个问题-当所有请求实际上都可以并行运行时,它会在循环内将请求进行菊花链式链接。这意味着它比需要的要慢。

稍微改变一下方法,我们可以确保Ajax请求是并行运行的,而不是一个接一个地运行:

async function (data, textStatus, jqXHR) {
    var todo = [], pending, results;

    // make a list of all the things we want to request
    $(json).each(async function (i, val) {
        $.each(val, function (key, value) {
            if (key.toLowerCase() == "jobid") todo.push(value);
        });
    });

    // request them all in parallel (=> array of promises)
    pending = todo.map(query_request);

    // wait for all of the results
    results = await Promise.all(pending)

    // ...now work with the results
}