首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >只有最后一个对象被推到对象数组(JavaScript)中。

只有最后一个对象被推到对象数组(JavaScript)中。
EN

Stack Overflow用户
提问于 2022-06-08 18:15:53
回答 1查看 51关注 0票数 1

我有一个函数,它本质上创建一个对象,然后将每个新创建的对象推送到一个对象数组中。但是,我面临的问题是,只有最后一个被创建的对象(在for循环中)被推到我的对象数组中。

我首先声明我的对象和对象数组:

代码语言:javascript
运行
复制
this.locationObjectArray = [];
this.locationObject = {};

然后,我声明一个等于"this“的变量,以便在回调中使用上面声明的对象和对象数组:

代码语言:javascript
运行
复制
var that = this;

然后,我读取了一个odata实体,它用指定的实体数据返回一个成功的回调:

代码语言:javascript
运行
复制
oModel.read("/Customers", {
                success: function (resp) {
                    var promises = [];
                    for (var x = 0; x < resp.results.length; x++) {
                        // Set tooltip property
                        var tooltip = resp.results[x].Country;
                        that.locationObject.tooltip = tooltip;
                        // Set type property
                        that.locationObject.type = "Inactive";
                        // Set position property
                        var request = $.ajax({
                            url: "https://api.opencagedata.com/geocode/v1/json?key=d3e40bf9b50247d4acf8122c543c5187&q=" + tooltip,
                            type: "GET",
                            dataType: 'json',
                            success: function (resp) {
                                that.locationObject.pos = resp.results[0].geometry.lng + ";" + resp.results[0].geometry.lat + ";0";
                            }
                        });
                        // Populate promises and locationObjectArray     
                        that.locationObjectArray.push(that.locationObject);
                        promises.push(request);
                        console.log(that.locationObject);
                    }
                    $.when.apply(null, promises).done(function(){
                        // console.log(that.locationObjectArray);
                        that.getView().getModel("map").setProperty("/Spots", that.locationObjectArray);
                    })
                }
            })

像在for循环中一样,我创建了一个名为答应的数组,我向API发出了一个Ajax请求,它每次循环时都会返回一个承诺。我需要包含每个请求(允诺),这样我就可以将函数的其余部分设置为只在每个请求(每个循环)中请求的所有数据都被接收之后才能运行。

然后创建我的for循环。

在for循环中,我开始设置先前声明的"locationObject“的每个属性。这些属性是:“工具提示”(locationObject.tooltip)、“类型”(locationObject.type)和"pos“(locationObject.pos)。两个属性“工具提示”和“类型”都是直接向前的。只有属性"pos“才会造成困难,因为每个循环中的成功回调结果都会返回这些数据。

尽管如此,我还是将新创建的对象推到对象数组中,并将该循环推送给承诺数组。

一旦for循环完成并解决了所有承诺,我就会设置我的数据模型。

虽然结果对象数组(locationObjectArray)的结果如下所示,但上面的内容看起来很好:

整个数组(对于每个循环)都使用最后一个循环的locationObject中收集的数据填充。

我试图在每个循环的开头重置对象(locationObject):

代码语言:javascript
运行
复制
...
for (var x = 0; x < resp.results.length; x++) {
    that.locationObject = {};
    ...

但是,这会干扰Ajax请求以获取每个对象的"pos“属性数据,并且生成的数组仅使用”工具提示“和”类型“属性集成功构建:

我不知道我能做些什么来解决这个问题,也不知道为什么现在对这些承诺置之不理,任何建议或建议都会受到欢迎。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-08 18:46:15

这段代码中有几个问题。我看到的主要问题是,您只有一个locationObject,您可以一次又一次地修改它并将其推入数组中。由于.push()推送了对该对象的引用(不创建副本),您只需在其中得到一个包含所有相同对象的数组,并且它具有您处理的上一项的值。

只要在循环中创建一个新的locationObject,就可以解决这个主要问题。以下是我建议重写的内容:

代码语言:javascript
运行
复制
oModel.read("/Customers", {
    success: async function(resp) {
        for (let result of resp.results) {
            const locationObject = {};
            const tooltip = result.Country;
            locationObject.type = "Inactive";
            const geoData = await $.ajax({
                url: "https://api.opencagedata.com/geocode/v1/json?key=d3e40bf9b50247d4acf8122c543c5187&q=" + tooltip,
                type: "GET",
                dataType: 'json',
            });
            locationObject.pos = geoData.results[0].geometry.lng + ";" + geoData.results[0].geometry.lat + ";0";
            that.locationObjectArray.push(that.locationObject);
        }
        that.getView().getModel("map").setProperty("/Spots", that.locationObjectArray);
    }
});

这使用了$.ajax()返回的承诺,并去掉了$.ajax()success回调。它还通过用for序列化await循环来简化代码。

如果希望并行运行所有ajax调用并避免使用await,可以这样做:

代码语言:javascript
运行
复制
oModel.read("/Customers", {
    success: function(resp) {
        Promise.all(resp.results.map(result => {
            const locationObject = {};
            const tooltip = result.Country;
            locationObject.type = "Inactive";
            return $.ajax({
                url: "https://api.opencagedata.com/geocode/v1/json?key=d3e40bf9b50247d4acf8122c543c5187&q=" + tooltip,
                type: "GET",
                dataType: 'json',
            }).then(geoData => {
                locationObject.pos = geoData.results[0].geometry.lng + ";" + geoData.results[0].geometry.lat + ";0";
                return locationObject;
            });
        })).then((locationArray) => {
            that.getView().getModel("map").setProperty("/Spots", locationObjectArray);
        });
    }
});

注意,这完全避免了使用that.locationObjectthat.locationObjectArray。结果是在内部收集和使用的,没有那些范围较高的变量。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72550428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档