Search code examples
javascriptpromiseparse-platformparse-cloud-codeback4app

Cannot set headers after they are sent to the client - Please help me understand this in my code


I've got this error in my Parse cloud code and I don't really understand how THIS SOLUTION applies to my code because I am using Parse cloud code. I do understand that the server is a via which runs Parse using javascript, which then runs CRUD actions in the database. But because it can't really be seen by the actual HTTP requests I can't tell whats happening and where I should adjust my code.

If someone could point out to me what I'm doing wrong and how I could adjust my code that would be great. Also is this even a big deal? If I leave my cloud code like below in production would this be a big deal? Everything runs perfectly as per high level results right now with this function.

I have the idea I should be continuing the .then() funtions. If this is the case, just how many long can this tree go?

Parse.Cloud.define("ccCreateGroupRole", async function(request){
    let user = request.user.id;
    let acl = new Parse.ACL();
    acl.setReadAccess(request.user, true);
    acl.setWriteAccess(request.user, true);
    let adminRole = new Parse.Role("Group_" + user, acl);
    adminRole.save(null, { useMasterKey: true }).then(function() {
        adminRole.getUsers().add(request.user);
        adminRole.save(null, { useMasterKey: true }).then(function() {
            console.log("Role created " + adminRole.id);
        });
    });

    // Create Sync Status objects
    let masterSyncStatus = {user: user, syncStatus: true};
    let newUserSyncStatus = {user: user, syncStatus: true};
    let masterArray = [];
    let newUserArray = [];
    masterArray.push(masterSyncStatus);
    newUserArray.push(newUserSyncStatus);

    // Initialize Sync Status class object by groupID
    let SyncStatus = Parse.Object.extend("SyncStatus");
      let syncStatus = new SyncStatus();
      syncStatus.set("groupName", "Group_" + user);
      syncStatus.set("masterSyncStatus", masterArray);
      syncStatus.set("newUserSyncStatus", newUserArray);
    await syncStatus.save(null, { useMasterKey: true });

    // Write own publicKey to user class
    let UserAddPublicKey = Parse.Object.extend("_User");
    let userAddPublicKey = new UserAddPublicKey();
    userAddPublicKey.set("objectId", request.user.id);
    userAddPublicKey.save(null, { useMasterKey: true });
  });


Solution

  • Your original code was not awaiting all the promises you have. Instead, you were using a mix of await and .then(), but not controlling the flow properly everywhere.

    When you nested all the .then() inside of each other, you were able to properly sequence all the asynchronous operations so that B waited until A was done and C waited until B was done. Your original code was not doing that.

    But, you can do all that with await too like this by using await on all asynchronous operations to make sure you're sequencing everything:

    Parse.Cloud.define("ccCreateGroupRole", async function(request) {
        let user = request.user.id;
        let acl = new Parse.ACL();
        acl.setReadAccess(request.user, true);
        acl.setWriteAccess(request.user, true);
        let adminRole = new Parse.Role("Group_" + user, acl);
        await adminRole.save(null, { useMasterKey: true });
        adminRole.getUsers().add(request.user);
        await adminRole.save(null, { useMasterKey: true });
        console.log("Role created " + adminRole.id);
    
        // Create Sync Status objects
        let masterSyncStatus = { user: user, syncStatus: true };
        let newUserSyncStatus = { user: user, syncStatus: true };
        let masterArray = [];
        let newUserArray = [];
        masterArray.push(masterSyncStatus);
        newUserArray.push(newUserSyncStatus);
    
        // Initialize Sync Status class object by groupID
        let SyncStatus = Parse.Object.extend("SyncStatus");
        let syncStatus = new SyncStatus();
        syncStatus.set("groupName", "Group_" + user);
        syncStatus.set("masterSyncStatus", masterArray);
        syncStatus.set("newUserSyncStatus", newUserArray);
        await syncStatus.save(null, { useMasterKey: true });
    
        // Write own publicKey to user class
        let UserAddPublicKey = Parse.Object.extend("_User");
        let userAddPublicKey = new UserAddPublicKey();
        userAddPublicKey.set("objectId", request.user.id);
        await userAddPublicKey.save(null, { useMasterKey: true });
    });