Deferred、Promises 和 Ajax 顺序不正确
Deferred, Promises, and Ajax not going in correct order
我正在尝试设置一个 Ajax 调用循环和一个在所有 Ajax 调用都已解决后 运行 的函数。我通读了一堆关于这个问题的 SO 问题,并认为我能够将它应用到我的代码中,但它不起作用,我终究无法弄清楚为什么。
这是JS代码。 map function
运行s 10 次仅供参考。
function addData(data) {
var deferreds = [];
$.map(data, function(job) {
deferreds.push(addLocation(job));
});
console.log(deferreds);
$.when.apply($, deferreds).then(mapData(data));
}
function addLocation(job) {
var dfd = $.Deferred(),
url = url;
console.log('in the addLocation function, outside the ajax call');
$.ajax({
url: url,
dataType: 'jsonp',
jsonp: 'json_callback'
}).done(function(location) {
job.lnglat = [parseFloat(location[0].lon), parseFloat(location[0].lat)];
console.log('resolved location');
dfd.resolve();
});
return dfd.promise();
}
function mapData(data) {
console.log('in the mapData function');
console.log(data);
var point = svg.selectAll('points')
.data(data);
point.exit().remove();
point.enter().append('circle')
.attr('r', 2.5);
point
.attr('cx', function(d) {
console.log(d); //shows d and has the lnglat but I think that is due to the developer tools reading the final result, not the result at the time
console.log(d.lnglat); // this gives undefined
console.log(d.lnglat[0]); // this gives an error as it hasn't been defined
console.log(projection(d.lnglat[0]));
return projection(d.lnglat[0])[0];
})
.attr('cy', function(d) {
return projection(d.lnglat[1])[1];
});
}
Chrome 开发人员工具报告以下顺序:
in the addLocation function, outside the ajax call //x10
[Object, object...] //this is the object list of deferred objects, there are 10 of them
in the mapData function
[Object, object..] //this is the object list of data from the mapData function
Object > ... //this is the d object in the mapData function > point anonymous function
undefined // this is the result of d.lnglat
Uncaught typeError ... // this is the result of d.lnglat[0] which doesn't exist yet
resolvedLocation //x10 this should be a lot higher right?
所以我希望 resolvedLocation console.log
到 运行 在 in the mapData function
到 运行 之前,我以为我已经这样设置了,但显然不是工作。我错过了什么?
正如 adeneo 在他的评论中所说,这里的问题是在
中直接调用 mapData
$.when.apply($, deferreds).then(mapData(data))
要解决这个问题,您需要使用 bind 来保持大部分解决方案的完整性(而不是对其进行太多更改)。
这应该有效:
$.when.apply($, deferreds).then(mapData.bind(this, data))
绑定不会延迟函数的调用。它将数据参数绑定到函数的调用,因此当 'then' 函数调用 mapData 时,它以 'data' 作为其参数,并且只有在所有承诺都已解决后才会发生。
我正在尝试设置一个 Ajax 调用循环和一个在所有 Ajax 调用都已解决后 运行 的函数。我通读了一堆关于这个问题的 SO 问题,并认为我能够将它应用到我的代码中,但它不起作用,我终究无法弄清楚为什么。
这是JS代码。 map function
运行s 10 次仅供参考。
function addData(data) {
var deferreds = [];
$.map(data, function(job) {
deferreds.push(addLocation(job));
});
console.log(deferreds);
$.when.apply($, deferreds).then(mapData(data));
}
function addLocation(job) {
var dfd = $.Deferred(),
url = url;
console.log('in the addLocation function, outside the ajax call');
$.ajax({
url: url,
dataType: 'jsonp',
jsonp: 'json_callback'
}).done(function(location) {
job.lnglat = [parseFloat(location[0].lon), parseFloat(location[0].lat)];
console.log('resolved location');
dfd.resolve();
});
return dfd.promise();
}
function mapData(data) {
console.log('in the mapData function');
console.log(data);
var point = svg.selectAll('points')
.data(data);
point.exit().remove();
point.enter().append('circle')
.attr('r', 2.5);
point
.attr('cx', function(d) {
console.log(d); //shows d and has the lnglat but I think that is due to the developer tools reading the final result, not the result at the time
console.log(d.lnglat); // this gives undefined
console.log(d.lnglat[0]); // this gives an error as it hasn't been defined
console.log(projection(d.lnglat[0]));
return projection(d.lnglat[0])[0];
})
.attr('cy', function(d) {
return projection(d.lnglat[1])[1];
});
}
Chrome 开发人员工具报告以下顺序:
in the addLocation function, outside the ajax call //x10
[Object, object...] //this is the object list of deferred objects, there are 10 of them
in the mapData function
[Object, object..] //this is the object list of data from the mapData function
Object > ... //this is the d object in the mapData function > point anonymous function
undefined // this is the result of d.lnglat
Uncaught typeError ... // this is the result of d.lnglat[0] which doesn't exist yet
resolvedLocation //x10 this should be a lot higher right?
所以我希望 resolvedLocation console.log
到 运行 在 in the mapData function
到 运行 之前,我以为我已经这样设置了,但显然不是工作。我错过了什么?
正如 adeneo 在他的评论中所说,这里的问题是在
中直接调用 mapData$.when.apply($, deferreds).then(mapData(data))
要解决这个问题,您需要使用 bind 来保持大部分解决方案的完整性(而不是对其进行太多更改)。 这应该有效:
$.when.apply($, deferreds).then(mapData.bind(this, data))
绑定不会延迟函数的调用。它将数据参数绑定到函数的调用,因此当 'then' 函数调用 mapData 时,它以 'data' 作为其参数,并且只有在所有承诺都已解决后才会发生。