如何使用JS async/await等待AJAX​​响应 [英] How to use JS async/await to wait for AJAX response

查看:175
本文介绍了如何使用JS async/await等待AJAX​​响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次使用Javascript中的async/await函数.我无法让脚本等待AJAX​​响应,然后继续进行操作,然后再读取/使用该响应.

I'm working with async/await functions in Javascript for the first time. I'm having trouble getting my script to wait for an AJAX response before proceeding and then reading/using that response.

我知道这里已经有很多关于异步/等待功能没有按预期等待的问题,但是其他问题的答案似乎都不适合我.

I know there are a lot of questions already on here regarding async/await functions not waiting as intended, but none of the answers to the other questions seemed to work for me.

基本上,我想做的是遍历层名称数组(对于OpenLayers映射),而forEach层名称我正在发送AJAX调用以检索记录(如果存在) )从MySQL数据库中获取.然后,我只显示结果,转到下一个图层名称,发送下一个AJAX调用,等等.

Basically, what I'm trying to do is loop through an array of layer names (for an OpenLayers map), and forEach layer name I'm sending an AJAX call to retrieve a record (if it exists) from a MySQL database. Then I simply display the result, move on to the next layer name, send the next AJAX call, etc.

这是我的代码:

async function getCellLayers() {
    layerNames = [];
    map.getLayers().forEach(function(layer) {
        if (layer.get('type') == "cell") {
            if (layer.getZIndex() == 100) {
                layerNames.push(layer.get('name'));
                if (layerNames.length == 1) {
                    fullExtent = layer.getSource().getExtent();
                } else {
                    ol.extent.extend(fullExtent, layer.getSource().getExtent());
                }
            }
        }
    });
    return layerNames;
}

async function getRecord(cell_date) {
    $.ajax({
        url: 'rec/getRecord/'+cell_date,
        type: 'get',
        dataType: 'json',
        success: await function(response){
          console.log("getRecord response: "+JSON.stringify(response));
          return response['data'];
      }
    });
}

async function testAsyncAwaitFunction() {
    let layerNames = await getCellLayers();
    layerNames.forEach(async function(layerName) {
        cell_date = layerName.substring(3)+"_"+window['currentImage'].substring(17,25);
        console.log(cell_date+":");
        let cellRecord = await getRecord(cell_date);
        console.log("Matches: "+cellRecord.length);
        console.log("testAsyncAwaitFunction response: "+JSON.stringify(cellRecord));
    });
}

我希望在控制台中看到这样的内容:

I'm expecting to see something like this in the console:

cell101_20190202:
getRecord response: {"data": [{"id":1,"record":"cell101_20190202","value":"0.8"}]}
Matches: 1
testAsyncAwaitFunction response: {"data": [{"id":1,"record":"cell101_20190202","value":"0.8"}]}
cell102_20190202:
getRecord response: {"data": [{"id":2,"record":"cell102_20190202","value":"0.7"}]}
Matches: 1
testAsyncAwaitFunction response: {"data": [{"id":2,"record":"cell102_20190202","value":"0.7"}]}
[ ... and so on ... ]

但是我却得到了:

cell101_20190202:
cell102_20190202:
(...)
getRecord response: {"data": [{"id":1,"record":"cell101_20190202","value":"0.8"}]}
getRecord response: {"data": [{"id":2,"record":"cell102_20190202","value":"0.7"}]}
(...)
getRecord response: {"data": [{"id":14,"record":"cell202_20190202","value":"0.6"}]}
(200x) Uncaught (in promise) TypeError: Cannot read property 'length' of undefined
getRecord response: {"data": [{"id":15,"record":"cell204_20190202","value":"0.5"}]}
(...)

我从没见过以testAsyncAwaitFunction response为前缀的JSON.stringify行,大概是因为该console.log命令之前的行试图获取cellRecord的长度,但由于AJAX响应尚未到达而失败.

I never see the JSON.stringify lines prefixed with testAsyncAwaitFunction response, presumably because the line before that console.log command, which attempts to get the length of cellRecord, fails as the AJAX response hasn't arrived yet.

我怀疑下面这行将是关键:

I suspect the following line will be the key here:

let cellRecord = await getRecord(cell_date);

但是我无法弄清楚为什么似乎没有一个正在等待"的人,即使上面几行的另一行看起来也很好:

but I can't work out why that one doesn't seem to be "awaiting" even though this other line a few lines above seems to be working just fine:

let layerNames = await getCellLayers();

非常感谢能更好地使用async/await的人员提供的帮助.我对PHP和Python更加习惯了,很难将自己的思维方式改变为异步思考.

Would really appreciate some help from someone with a better grasp of using async/await. I'm much more accustomed to PHP and Python and am having a hard time changing my mindset to thinking asynchronously.

推荐答案

此处有两件事: -您的getRecord函数不会返回Promise,因此,等待不会等待任何东西 -forEach不能与异步功能一起使用,因为实现不会等待.

Two things here: - Your getRecord function does not return a Promisetherefore, the await doesn't wait for anything - forEachcannot work with async functions, as the implementation does not await.

对于第一个问题,您可以通过执行以下操作来解决它:

For the first problem you can solve it by doing:

async function getRecord(cell_date) {
    return $.ajax({
        url: 'rec/getRecord/'+cell_date,
        type: 'get',
        dataType: 'json',
    })
    .then(response => response.data);
}

对于第二个问题,您可以通过以下方式运行循环来实现:

For the second problem, you can do it by running a loop this way:

async function testAsyncAwaitFunction() {
    let layerNames = await getCellLayers();
    for (layerName of layerNames) {

        cell_date = layerName.substring(3)+"_"+window['currentImage'].substring(17,25);
        console.log(cell_date+":");
        let cellRecord = await getRecord(cell_date);
        console.log("Matches: "+cellRecord.length);
        console.log("testAsyncAwaitFunction response: "+JSON.stringify(cellRecord));

    }
}

但是,这样做会使所有内容一一运行.通过发送请求,然后使用Promise.all这样等待所有请求完成,您甚至可以做得更好:

But doing this makes everything run one by one. You could do even better by sending the requests and then waiting for all of them to complete using Promise.all this way:

const promises = []
for (layerName of layerNames) {
        cell_date = layerName.substring(3)+"_"+window['currentImage'].substring(17,25);
        console.log(cell_date+":");
        promises.push(getRecord(cell_date));
}
const records = await Promise.all(promises)

这篇关于如何使用JS async/await等待AJAX​​响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆