javascript - 如何使用 JS async/await 等待 AJAX 响应
问题描述
我第一次在 Javascript 中使用 async/await 函数。在继续阅读/使用该响应之前,我无法让我的脚本等待 AJAX 响应。
我知道这里已经有很多关于 async/await 函数没有按预期等待的问题,但其他问题的答案似乎对我没有用。
基本上,我要做的是遍历图层名称数组(用于OpenLayers
地图),以及forEach
图层名称我发送 AJAX 调用以从 MySQL 数据库中检索记录(如果存在)。然后我简单地显示结果,转到下一层名称,发送下一个 AJAX 调用,等等。
这是我的代码:
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));
});
}
我期待在控制台中看到这样的东西:
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"}]}
(...)
我从来没有看到以JSON.stringify
为前缀的行testAsyncAwaitFunction response
,大概是因为试图获取 cellRecord 长度的 console.log 命令之前的行失败,因为 AJAX 响应尚未到达。
我怀疑以下行将是这里的关键:
let cellRecord = await getRecord(cell_date);
但我无法弄清楚为什么那个似乎没有“等待”,即使上面几行的另一行似乎工作得很好:
let layerNames = await getCellLayers();
非常感谢能更好地掌握使用 async/await 的人的帮助。我更习惯于 PHP 和 Python,并且很难将我的思维方式转变为异步思考。
解决方案
这里有两件事: - 您的getRecord
函数不返回 aPromise
因此,await 不等待任何东西 -forEach
不能与异步函数一起使用,因为实现不等待。
对于第一个问题,您可以通过以下方式解决:
async function getRecord(cell_date) {
return $.ajax({
url: 'rec/getRecord/'+cell_date,
type: 'get',
dataType: 'json',
})
.then(response => response.data);
}
对于第二个问题,您可以通过以下方式运行循环来完成:
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
:
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)
推荐阅读
- arrays - 如何创建具有不同线长的二维数组倒计时?
- css - 如何使用引导程序垂直显示单选按钮
- python - 计算百分比变化(多变量) Pandas
- ruby-on-rails - 如何测试 ActiveSupport::TaggedLogging
- git - 如何使用 git 仅授予对部分 repo 的访问权限?
- php - 这个sql查询怎么注入?
- javascript - React Native 性能:Javascript 与 Typescript
- reactjs - 如何在不安装表单的情况下在 React 中发起发布请求?
- angular - Angular Material 表数据源问题
- ios - 在后台执行 Apple 快捷方式