1

我正在尝试将一个新的属性值推送到现有的 JSONArray 中,但是当我这样做时,我得到了错误TypeError: Cannot set property 'live' of undefined

var ProxyData       =   [];

//Setting some of the fields outside the for loop
ProxyData.push({
                    'country'       :   country,
                    'ip'            :   ip,
                    'port'          :   port,
                    'createdAt'     :   createdAt,
                    'updatedAt'     :   updatedAt,
                    'provider'      :   'proxy11.com'
                });

//Based on some value I need to add thie live field
for(var item=0; item<ProxyData.length; item++)
{
    ProxyData[item].live    =   'Yes';

}

我想保留先前设置的对象,但同时基于 for 循环中的某些条件,我想将新字段添加live到数组中的对象中。我怎样才能做到这一点?

我也试过了,但没有运气: ProxyData[item]["live"] = "Yes";

我之前尝试定义该live字段,以便稍后进行设置,但仍然无法正常工作:

ProxyData.push({
                            'country'       :   country,
                            'ip'            :   ip,
                            'port'          :   port,
                            'createdAt'     :   createdAt,
                            'updatedAt'     :   updatedAt,
                            'provider'      :   'proxy11.com',
                            'live'          :   ''
                        });

我发布了上面的代码是为了简单理解,但为了清楚起见,我将发布我项目中的完整代码:

var ProxyData       =   [];

for(var itemCount=0; itemCount<pageData.data.length; itemCount++)
{
    var country     =   pageData.data[itemCount].country;
    var ip          =   pageData.data[itemCount].ip;
    var port        =   pageData.data[itemCount].port;
    var createdAt   =   pageData.data[itemCount].createdAt;
    var updatedAt   =   pageData.data[itemCount].updatedAt;

    ProxyData.push({
        'country'       :   country,
        'ip'            :   ip,
        'port'          :   port,
        'createdAt'     :   createdAt,
        'updatedAt'     :   updatedAt,
        'provider'      :   'proxy11.com'
    });

    itemProcessed++;

    if(itemProcessed == pageData.data.length)
    {

        var     sql     =   " INSERT INTO TBL_PROXY (IP, COUNTRY, PORT, CREATED_DT_TM, UPDATE_DT_TM, PROVIDER) VALUES ";

        for(var item=0; item<ProxyData.length; item++)
        {
            var proxy       =   'http://'+ProxyData[item].ip+':'+ProxyData[item].port;
            var liveState   =   "";

            request({
                'url':'localhost:3000',
                'method': "GET",
                'proxy': proxy
            },function (error, response, body) {

                if (!error && response.statusCode == 200) {
                    ProxyData[item].live    =   'Yes';
                    console.log(ProxyData);
                }
                else
                {
                    ProxyData[item].live    =   'No';
                    console.log(ProxyData);
                }
            });

            sql         +=  util.format(" (%s', '%s', '%s', '%s', '%s', '%s') ", ProxyData[item].ip, ProxyData[item].country, ProxyData[item].port, ProxyData[item].createdAt, ProxyData[item].updatedAt, ProxyData[item].provider)+',';
        }



        sql     =   sql.slice(0, sql.length-1);

        db.Proxy_Feed_Data_Push(sql, function(data){
            callback(data);
        });
    }
}
4

1 回答 1

1

当你的异步调用完成时,“ item”的值已经改变了。尝试添加console.log(item, ProxyData[item]);function (error, response, body) {查看。

另一种看待这种现象的方法是用这个简单的例子:

var ProxyData = ['a', 'b', 'c'];
for (var item = 0; item < ProxyData.length; item++) {
  Promise.resolve().then(() => {
    console.log(item, ProxyData[item]);
  });
}
// Results in:
// 3 undefined
// 3 undefined
// 3 undefined

现代 JavaScript 环境中,简单地使用let而不是var修复这个问题。

由于其作用域仅限于定义它的函数(而不是块),因此一种解决方法是(1)用函数包装每个循环迭代并(2)定义一个新变量(3),其var值为item调用结束,它使用正确的特别为它定义的变量。

    for(var item=0; item<ProxyData.length; item++)
    {
        // (1) wrap in a IIFE
        // (2) define a new variable
        (function(item2) {

            var proxy       =   'http://'+ProxyData[item].ip+':'+ProxyData[item].port;
            var liveState   =   "";

            request({
                'url':'localhost:3000',
                'method': "GET",
                'proxy': proxy
            },function (error, response, body) {
                // Even though 'item' has changed by now,
                // the variable 'item2' is scoped to the function
                // inside the loop iteration so it's what you expect.

                if (!error && response.statusCode == 200) {
                    ProxyData[item2].live    =   'Yes';
                    console.log(ProxyData);
                }
                else
                {
                    ProxyData[item2].live    =   'No';
                    console.log(ProxyData);
                }
            });

            sql         +=  util.format(" (%s', '%s', '%s', '%s', '%s', '%s') ", ProxyData[item].ip, ProxyData[item].country, ProxyData[item].port, ProxyData[item].createdAt, ProxyData[item].updatedAt, ProxyData[item].provider)+',';

        // (3) pass the value of 'item', it'll be assigned to 'item2'
        })(item);
    }

可以item2将变量命名为item,但这可能会造成混淆。

或者只使用块范围的变量来代替定义函数:

    let item2 = item;
    // When you run your async call later, it'll have
    // the correct value because 'let' is scoped to the 
    // nearest block (which is 'for() {}').
于 2020-06-23T14:26:19.603 回答