Non-empty array response never returned

Hey all! Hope everyone’s having a great day! I just finished upgrading my Parse Server, from 2.8.4 to 4.3.0 and I’ve found out that there are many cloud functions, not all of them, that even though the queries fetch results, the responses come back nil.

Here’s one example, where studentObjectsArray contains 20 elements (I’ve checked) and the response to my iOS app is nil;

Parse.Cloud.define("getStudentsOfDepartmentFunction", async (request) => {
	const currentUserId = request.user.id;

	const {
		departmentId, skipNumber
	} = request.params;

	// ---------------------------------
	
    blockModule.getUserBlocksWithCallback(currentUserId, async function(blockedUsersArray) {
	    const getStudentsOfDepartmentQuery = new Parse.Query(Parse.User);

	    getStudentsOfDepartmentQuery.equalTo("department.id", departmentId);
	    getStudentsOfDepartmentQuery.include("coverMiddle");
	    getStudentsOfDepartmentQuery.limit(20);
	    getStudentsOfDepartmentQuery.skip(skipNumber);
	    getStudentsOfDepartmentQuery.descending("karma");

	    try {
	    	const studentObjectsArray = await getStudentsOfDepartmentQuery.find();
		    return studentObjectsArray;
	    } catch (error) {
	    	throw error;
	    }
    });
});

Any idea what could be wrong?

EDIT; I tried removing the blockModule.getUserBlocksWithCallback function call and now the client is receiving the response properly! Here’s that function’s implementation; (note that the function itself works just fine)

module.exports = {
	getUserBlocksWithCallback: async function(currentUserId, callback) {
		var currentUser = new Parse.User();
		currentUser.set("objectId", currentUserId);
	
		// ---------------------------------
		
		var thoseWhoBlockMeQuery = new Parse.Query("BlockedUser");
		thoseWhoBlockMeQuery.equalTo("blockedUsers", currentUserId);
	
		var thoseIBlockQuery = new Parse.Query("BlockedUser");
		thoseIBlockQuery.equalTo("user", currentUser);
	
		var blocksFinalQuery = Parse.Query.or(thoseWhoBlockMeQuery, thoseIBlockQuery);
	
		// ---------------------------------
		
		try {
			const blockObjectsArray = await blocksFinalQuery.find();

			// ---------------------------------
			
			var blocksArray = [];
		
			for (var i = 0; i < blockObjectsArray.length; i++) {
				if (blockObjectsArray[i].get("user").id == currentUserId) {
					var blockedUserIdsArray = blockObjectsArray[i].get("blockedUsers");

					for (var j = 0; j < blockedUserIdsArray.length; j++) {
						var blockedUser = new Parse.User();
						blockedUser.set("objectId", blockedUserIdsArray[j]);

						blocksArray.push(blockedUser);
					}
				}
				else {
					var blockedUser = blockObjectsArray[i].get("user");
					blocksArray.push(blockedUser);
				}
			}

			// ---------------------------------
			
			callback(blocksArray);
		} catch (error) {
			callback([]);
		}
	}
};

Your cloud code function is not returning the result and that’s why you have null. When you do return studentObjectsArray;, you are actually returning the value of the callback function and not of the cloud function. You’d need to refactor to something like this:

Parse.Cloud.define("getStudentsOfDepartmentFunction", async (request) => {
	const currentUserId = request.user.id;

	const {
		departmentId, skipNumber
	} = request.params;

	// ---------------------------------
	
    return await (new Promise((resolve, reject) => blockModule.getUserBlocksWithCallback(currentUserId, async function(blockedUsersArray) {
	    const getStudentsOfDepartmentQuery = new Parse.Query(Parse.User);

	    getStudentsOfDepartmentQuery.equalTo("department.id", departmentId);
	    getStudentsOfDepartmentQuery.include("coverMiddle");
	    getStudentsOfDepartmentQuery.limit(20);
	    getStudentsOfDepartmentQuery.skip(skipNumber);
	    getStudentsOfDepartmentQuery.descending("karma");

	    try {
	    	const studentObjectsArray = await getStudentsOfDepartmentQuery.find();
		    resolve(studentObjectsArray);
	    } catch (error) {
	    	reject(error);
	    }
    })));
});
1 Like

Thanks man! It works!! Can this be achieved without the use of Promises?

Yes… but you have to refactor your blockModule.getUserBlocksWithCallback and get rid of the callback function.

1 Like

So it returns the response instead of callbacking it? (yeah I know callbacking isn’t a word :stuck_out_tongue_winking_eye:)

Yes. Something like this:

module.exports = {
	getUserBlocksWithCallback: async currentUserId => {
		var currentUser = new Parse.User();
		currentUser.set("objectId", currentUserId);
	
		// ---------------------------------
		
		var thoseWhoBlockMeQuery = new Parse.Query("BlockedUser");
		thoseWhoBlockMeQuery.equalTo("blockedUsers", currentUserId);
	
		var thoseIBlockQuery = new Parse.Query("BlockedUser");
		thoseIBlockQuery.equalTo("user", currentUser);
	
		var blocksFinalQuery = Parse.Query.or(thoseWhoBlockMeQuery, thoseIBlockQuery);
	
		// ---------------------------------
		
		try {
			const blockObjectsArray = await blocksFinalQuery.find();

			// ---------------------------------
			
			var blocksArray = [];
		
			for (var i = 0; i < blockObjectsArray.length; i++) {
				if (blockObjectsArray[i].get("user").id == currentUserId) {
					var blockedUserIdsArray = blockObjectsArray[i].get("blockedUsers");

					for (var j = 0; j < blockedUserIdsArray.length; j++) {
						var blockedUser = new Parse.User();
						blockedUser.set("objectId", blockedUserIdsArray[j]);

						blocksArray.push(blockedUser);
					}
				}
				else {
					var blockedUser = blockObjectsArray[i].get("user");
					blocksArray.push(blockedUser);
				}
			}

			// ---------------------------------
			
			return blocksArray;
		} catch (error) {
			return [];
		}
	}
};

Then your cloud code could be:

Parse.Cloud.define("getStudentsOfDepartmentFunction", async (request) => {
	const currentUserId = request.user.id;

	const {
		departmentId, skipNumber
	} = request.params;

	// ---------------------------------
	
const blockedUsersArray = await blockModule.getUserBlocksWithCallback(currentUserId);

	    const getStudentsOfDepartmentQuery = new Parse.Query(Parse.User);

	    getStudentsOfDepartmentQuery.equalTo("department.id", departmentId);
	    getStudentsOfDepartmentQuery.include("coverMiddle");
	    getStudentsOfDepartmentQuery.limit(20);
	    getStudentsOfDepartmentQuery.skip(skipNumber);
	    getStudentsOfDepartmentQuery.descending("karma");

	    try {
	    	const studentObjectsArray = await getStudentsOfDepartmentQuery.find();
		    return studentObjectsArray;
	    } catch (error) {
	    	throw error;
	    }
});
1 Like