Deferred,Promises和Ajax的顺序不正确

时间:2015-01-17 19:56:41

标签: javascript jquery ajax

我试图建立一个Ajax调用循环和一个在所有Ajax调用解决后运行的函数。我读了很多关于这个问题的SO问题,并认为我能够将它应用到我的代码中,但它不起作用,我不能为我的生活找出原因。

这是JS代码。 map function运行10次FYI。

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.login the mapData function之前运行,我认为我已经设置了这个,但它显然不起作用。我错过了什么?

1 个答案:

答案 0 :(得分:1)

正如阿德内诺在评论中所说,这里的问题是

中的mapData的imidiate调用
  

$。when.apply($,deferreds).then(mapData(data))

要解决此问题,您需要使用bind来保持大多数解决方案的完整性(并且不要更改它)。 这应该有效:

  

$。when.apply($,deferreds).then(mapData.bind(this,data))

绑定不会延迟函数的调用。它将data参数绑定到函数的调用,因此当'then'函数调用mapData时,它会以'data'作为参数,并且只有在所有promise都被解析后才会发生。