javascript - jquery延迟返回太早
问题描述
我有以下代码:
$.when(multipleQueries(stateQueries, rowData))
.then(function (data) {
//do stuff with data - removed for brevity
多重查询功能如下:
function multipleQueries(queriesToExecute, rowData) {
var allQueriesMapped = $.Deferred();
// If a single query has been provided, convert it into an array
if (Array.isArray(queriesToExecute) === false) {
queriesToExecute = [].concat(queriesToExecute);
}
// Create a function for each region to run the query.
$.when.apply($, $.map(queriesToExecute, function (query) {
// Execute the query in the region
return $.when(executeQuery(query.InstanceInfo, query.Query)).then(function (data) {
var isDataMapped = $.Deferred();
var mappedData = [];
// Perform some data transformation
$.when.apply($, $.map(data.results, function (value) {
var properties = value.succinctProperties;
//code removed for brevity
return $.when(mapData(properties)).then(function (mappedRow) {
if (mappedRow) {
mappedData.push(mappedRow);
}
});
})).then(function () {
isDataMapped.resolve({
results: mappedData,
numItems: mappedData.length
});
});
return isDataMapped.promise();
}).then(function (data) {
debugger;
allQueriesMapped.resolve(data);
});
}));
return allQueriesMapped.promise();
}
我遇到的问题是,我传入了 5 个查询来执行 multipleQueries 函数,但它在运行第一个查询后到达调试器行 - 然后解析 allQueriesMapped deferred,然后返回到 do 数据它是从哪里调用的,但是因为我没有来自我传入的 5 个 queires 的所有数据,所以我没有看到预期的行为 - 我如何设置这些承诺有什么遗漏吗?
注意 - 我尝试将调试器之前的 .then 更改为 .done 但得到相同的行为,并且还尝试将调用代码更改为 .done ,如下所示,但也得到相同的结果。
$.when(multipleQueries(stateQueries, rowData))
.done(function (data) {
//do stuff with data - removed for brevity
** 更新 - 执行查询功能如下
function executeQuery(instanceInfo, query) {
return $.ajax({
url: instanceInfo.Url,
type: 'GET',
data: {
q: query,
succinct: true
},
processData: true
});
}
解决方案
正如 freen-m 和 charlietfl 指出的那样,这then
是在错误的地方(见***
评论):
function multipleQueries(queriesToExecute, rowData) {
var allQueriesMapped = $.Deferred();
// If a single query has been provided, convert it into an array
if (Array.isArray(queriesToExecute) === false) {
queriesToExecute = [].concat(queriesToExecute);
}
// Create a function for each region to run the query.
$.when.apply($, $.map(queriesToExecute, function(query) {
// Execute the query in the region
return $.when(executeQuery(query.InstanceInfo, query.Query)).then(function(data) {
var isDataMapped = $.Deferred();
var mappedData = [];
// Perform some data transformation
$.when.apply($, $.map(data.results, function(value) {
var properties = value.succinctProperties;
//code removed for brevity
return $.when(mapData(properties)).then(function(mappedRow) {
if (mappedRow) {
mappedData.push(mappedRow);
}
});
})).then(function() {
isDataMapped.resolve({
results: mappedData,
numItems: mappedData.length
});
});
return isDataMapped.promise();
}).then(function(data) { // ***
debugger; // ***
allQueriesMapped.resolve(data); // ***
});
}));
return allQueriesMapped.promise();
}
它在里面map
,当它应该在外面时:
function multipleQueries(queriesToExecute, rowData) {
var allQueriesMapped = $.Deferred();
// If a single query has been provided, convert it into an array
if (Array.isArray(queriesToExecute) === false) {
queriesToExecute = [].concat(queriesToExecute);
}
// Create a function for each region to run the query.
$.when.apply($, $.map(queriesToExecute, function(query) {
// Execute the query in the region
return $.when(executeQuery(query.InstanceInfo, query.Query)).then(function(data) {
var isDataMapped = $.Deferred();
var mappedData = [];
// Perform some data transformation
$.when.apply($, $.map(data.results, function(value) {
var properties = value.succinctProperties;
//code removed for brevity
return $.when(mapData(properties)).then(function(mappedRow) {
if (mappedRow) {
mappedData.push(mappedRow);
}
});
})).then(function() {
isDataMapped.resolve({
results: mappedData,
numItems: mappedData.length
});
});
return isDataMapped.promise();
});
})).then(function(data) {
debugger;
allQueriesMapped.resolve(data);
});
return allQueriesMapped.promise();
}
但是那里有很多不必要的使用$.when
and new $.Deferred
(见*** 1
评论),你可以更简单地将你的参数包装在一个数组中(见*** 2
评论:
function multipleQueries(queriesToExecute, rowData) {
// If a single query has been provided, convert it into an array
if (Array.isArray(queriesToExecute) === false) {
queriesToExecute = [queriesToExecute]; // *** 2
}
// Create a function for each region to run the query.
return $.when.apply($, $.map(queriesToExecute, function(query) { // *** 1
// Execute the query in the region
return executeQuery(query.InstanceInfo, query.Query).then(function(data) { // *** 1
var mappedData = [];
// Perform some data transformation
return $.when.apply($, $.map(data.results, function(value) {
var properties = value.succinctProperties;
//code removed for brevity
return mapData(properties).then(function(mappedRow) { // *** 1
if (mappedRow) {
mappedData.push(mappedRow);
}
});
})).then(function() {
return {
results: mappedData,
numItems: mappedData.length
};
});
});
}));
}
new
当你已经有了一个承诺时,就再也不需要通过;创建一个新的承诺了。只需使用返回的then
. 此外,当您已经有一个承诺时,就永远不需要使用$.when(thePromise)
.
您可能还受益于切换到内置的 Promise 语义而不是Deferred
早期的 jQuery:
function multipleQueries(queriesToExecute, rowData) {
// If a single query has been provided, convert it into an array
if (Array.isArray(queriesToExecute) === false) {
queriesToExecute = [queriesToExecute];
}
// Create a function for each region to run the query.
return Promise.all(queriesToExecute.map(function(query) {
// Execute the query in the region
return executeQuery(query.InstanceInfo, query.Query).then(function(data) {
return Promise.all(data.results.map(function(value) {
var properties = value.succinctProperties;
//code removed for brevity
return mapData(properties);
}).then(function(mappedData) {
mappedData = mappedData.filter(Boolean); // Remove the falsy ones from `mapData`
return {
results: mappedData,
numItems: mappedData.length
};
});
});
}));
}
Promise.all
对于处理一系列承诺非常有用。但请确保您使用的是最新的 jQuery,早期版本的 Deferred 无法与真正的 Promise 正确互操作。我不知道(也无法立即找到)该问题何时修复。
推荐阅读
- xamarin.forms - 检测何时因关闭权限对话框而调用 OnResume
- testing - html-testrail 没有在 testcafe 中捕获失败的测试
- php - 在每个目录的 .htacess 中使用 SetHandler 设置特定的 PHP 版本不起作用
- ansible - Ansible如何在循环中忽略未定义的项目
- leaflet - 带有传单地图的 R Shiny 应用程序未以选定点为中心
- c# - 为什么即使有十进制数,第三列也为空?
- node.js - 节点 HTTP/2 设置托管证书的正确位置
- angular - ngrx 如何从存储中获取嵌套属性值
- sql - 根据列值是否存在于另一个视图中创建 SQL 视图
- gcc - gcc 自动链接静态库所需的共享库