Node.js TypeError无法读取未定义的属性objectId

Posted

技术标签:

【中文标题】Node.js TypeError无法读取未定义的属性objectId【英文标题】:Node.js TypeError Cannot read property objectId of undefined 【发布时间】:2016-06-10 16:41:51 【问题描述】:

我想使用 REST API 导入 Parse.com 的 JSON 文件是:

     "results": [ 
 "TELEPHONE NUMBER":"555", 
"FAMILY NAMES":"smith, john", 
"objectId": "y6rwllkJhz", 
"STREET ADDRESS":"555 street", 
"CITY, STATE, ZIP CODE":"Town, ST 12345", 
"E-MAIL ADDRESS":"" 
]

顺便说一句,里面有几个条目,每个条目都代表不同的家庭,为了便于阅读,我只保留了一个。

我正在使用以下 JS 尝试将其导入新类

var PARSE_APPLICATION_ID = 'APPID';
var PARSE_REST_API_KEY = 'RESTKEY';

var JSON_FILE_PATH = '/Users/path/Directory.json'; // Path to JSON file to import
var IMPORTED_CLASS_NAME = 'Directory2'; // Class to import
var POINTING_CLASS_NAME = 'Directory'; // Class with pointers to imported class
var POINTING_CLASS_PROPERTY = 'String'; // Name of pointer property

var request = require('request');
var fs = require('fs');

// Import objects from JSON to Parse
importFromJson(JSON_FILE_PATH, IMPORTED_CLASS_NAME, function(newObjectIds) 
    console.log('Successfully imported objects from JSON.');
    // Update objects from external Parse class pointing to imported objects
    updatePointingObjects(IMPORTED_CLASS_NAME, POINTING_CLASS_NAME, POINTING_CLASS_PROPERTY, newObjectIds, function() 
        console.log('Successfully updated pointing objects.');
    );
);


function importFromJson(jsonFilePath, importedClassName, callback) 
    // Store new objectIds associated to their original objectIds
    // Will be used to update pointers of other Parse classes
    var newObjectIds = ;

    // Read and parse JSON file
    var json = JSON.parse(fs.readFileSync(jsonFilePath, 'utf8'));

    // Delay requests with setTimeout to stay under Parse's limit
    delayedAsyncLoop(function(i, fnCallback) 
            // Loop
            var obj = json.results.length[i - 1];
            var originalObjectId = obj.objectId;
            // Create object using Parse REST API
            createObject(importedClassName, obj, function(newObj) 
                // Abort if request fails
                if (!newObj) process.exit(-1);
                // Associate the object's new objectId to its original objectId
                newObjectIds[originalObjectId] = newObj.objectId;
                fnCallback();
            );
        ,
        json.results.length, // Iterations

        100, // Delay in milliseconds
        function()  // Done looping
            callback(newObjectIds);
        );


function updatePointingObjects(importedClassName, pointingClassName, pointingClassProperty, newObjectIds, callback) 
    // Get all objects from another Parse class that point to our imported class
    getAllPointingObjects(pointingClassName, pointingClassProperty, function(pointingObjects) 
        // Abort if request fails
        if (!pointingObjects) process.exit(-1);

        var nbObjectsToUpdate = pointingObjects.length;
        // Delay requests with setTimeout to stay under Parse's limit
        delayedAsyncLoop(function(i, fnCallback) 
                // Loop
                var pointingObject = pointingObjects[i - 1];
                var pointer = pointingObject[pointingClassProperty];
                if (!pointer || pointer.className != importedClassName) 
                    fnCallback();
                    nbObjectsToUpdate--;
                    if (!nbObjectsToUpdate) callback(); // Done updating pointing objects
                    return;
                
                // Retrieve the new objectId each pointer should be updated with
                var originalObjectId = pointer.objectId;
                var newObjectId = newObjectIds[originalObjectId];
                if (!newObjectId) 
                    fnCallback();
                    nbObjectsToUpdate--;
                    if (!nbObjectsToUpdate) callback(); // Done updating pointing objects
                    return;
                
                // Update pointer to the new objectId
                updatePointingObject(pointingClassName, pointingClassProperty, pointingObject.objectId, importedClassName, newObjectId, function() 
                    fnCallback();
                    nbObjectsToUpdate--;
                    if (!nbObjectsToUpdate) callback(); // Done updating pointing objects
                );
            ,
            pointingObjects.length, // Iterations
            100 // Delay in milliseconds
        );
    );



function delayedAsyncLoop (fn, iterations, delay, callback) 
    (function loop (i, done) 
        setTimeout(function() 
            fn(i, function() 
                if (--i) 
                    // Keep looping
                    loop(i, done);
                 else 
                    // Loop done
                    if (done) done();
                
            );
        , delay)
    )(iterations, callback);


function createObject(className, object, callback) 
    delete object.objectId;
    delete object.createdAt;
    delete object.updatedAt;

    request(
        method: 'POST',
        url: 'https://api.parse.com/1/classes/' + className,
        headers: 
            'X-Parse-Application-Id': PARSE_APPLICATION_ID,
            'X-Parse-REST-API-Key': PARSE_REST_API_KEY,
            'Content-Type': 'application/json; charset=UTF-8'
        ,
        body: JSON.stringify(object)
    , function(error, response, body) 
        if (response.statusCode == 201) 
            var result = JSON.parse(body);

            object.objectId = result.objectId;
            object.createdAt = result.createdAt;
            object.updatedAt = result.updatedAt;

            console.log('Created ' + className + ' object with objectId ' + result.objectId);
            callback(object);
         else 
            console.log('Error: ' + response.statusCode);
            console.log(body);
            callback();
        
    );


function getAllPointingObjects(className, pointingProperty, callback) 
    getPointingObjectsRecursive([], className, pointingProperty, 0, null, callback)


function getPointingObjectsRecursive(allObjects, className, pointingProperty, skipNb, minCreatedAt, callback) 
    var whereObj = ;
    whereObj[pointingProperty] = 
        '$exists': true
    ;
    if (minCreatedAt) 
        whereObj['createdAt'] = 
            '$gt': minCreatedAt
        ;
    
    var queryString = 
        'limit': 1000,
        'order': 'createdAt',
        'skip': skipNb,
        'where': JSON.stringify(whereObj)
    ;

    request(
        method: 'GET',
        url: 'https://api.parse.com/1/classes/' + className,
        headers: 
            'X-Parse-Application-Id': PARSE_APPLICATION_ID,
            'X-Parse-REST-API-Key': PARSE_REST_API_KEY
        ,
        qs: queryString
    , function(error, response, body) 
        if (response.statusCode == 200) 
            var results = JSON.parse(body).results;
            Array.prototype.push.apply(allObjects, results);
            if (results.length == 1000) 
                // Keep fetching
                if (skipNb > 10000) 
                    minCreatedAt = results[999].createdAt;
                    skipNb = 0;
                
                getPointingObjectsRecursive(allObjects, className, pointingProperty, skipNb+1000, minCreatedAt, callback);
             else 
                // All objects fetched
                callback(allObjects);
            
         else 
            console.log('Error: ' + response.statusCode);
            console.log(body);
            callback();
        
    );


function updatePointingObject(pointingClassName, pointingClassProperty, pointingObjectId, pointedClassName, pointedObjectId, callback) 
    var pointer = 
        "__type": "Pointer",
        "className": pointedClassName,
        "objectId": pointedObjectId
    ;

    var requestBody = ;
    requestBody[pointingClassProperty] = pointer;

    request(
        method: 'PUT',
        url: 'https://api.parse.com/1/classes/' + pointingClassName + '/' + pointingObjectId,
        headers: 
            'X-Parse-Application-Id': PARSE_APPLICATION_ID,
            'X-Parse-REST-API-Key': PARSE_REST_API_KEY,
            'Content-Type': 'application/json; charset=UTF-8'
        ,
        body: JSON.stringify(requestBody)
    , function(error, response, body) 
        if (response.statusCode == 200) 
            console.log('Updated pointer of ' + pointingClassName + '/' + pointingObjectId + ' to ' + pointedObjectId);
            callback();
         else 
            console.log('Error: ' + response.statusCode);
            console.log(body);
            callback();
        
    );

问题是我收到以下错误:

TypeError: Cannot read property 'objectId' of undefined

我不明白为什么,因为它是有效的 JSON 并且 objectId 在那里。

【问题讨论】:

这里发生了太多事情。哪一行导致该错误? 您希望json.results.length[i - 1] 发生什么?因为这不是你索引数组的方式 @mrwillihog 错误是这一行,比如 35 什么的:var originalObjectId = obj.objectId; var obj = json.results.length[i - 1]; 那行没有意义。 length 应该返回一个整数 - results 的长度。我想你想做的是var obj = json.results[i - 1]; @mrwillihog 完美解决了!!谢谢! 【参考方案1】:

试试result.results[0].objectId

【讨论】:

【参考方案2】:

这个作业看起来很糟糕: var obj = json.results.length[i - 1];

.length 为您提供数组的大小。看起来您可能正在尝试对数组进行索引,并从数组中一个一个地取出每个对象。

也许它应该更像:

var obj = json.results[ json.results.length + (i - 1) ]; 假设 i != 0

【讨论】:

该错误意味着 obj 没有该属性。由于obj是从json.results分配的,所以检查var jsonJSON.parse分配后有什么属性,然后在错误点。

以上是关于Node.js TypeError无法读取未定义的属性objectId的主要内容,如果未能解决你的问题,请参考以下文章

Node.js Discord.js UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性“calculatedPosition”

Node.js TypeError:无法读取未定义的属性“作者”

Node.js TypeError无法读取未定义的属性objectId

Node.js 和 jdbc:TypeError:无法读取未定义的属性“url”

Node.js:在没有返回记录的 SQL 查询中:TypeError:无法读取未定义的属性

错误:TypeError:尝试为网站 node.js 注册用户时无法读取未定义的属性“catch”