将标头发送到客户端后无法设置标头-请帮助我在代码中理解这一点

Posted

技术标签:

【中文标题】将标头发送到客户端后无法设置标头-请帮助我在代码中理解这一点【英文标题】:Cannot set headers after they are sent to the client - Please help me understand this in my code 【发布时间】:2021-12-31 06:06:26 【问题描述】:

我的 Parse 云代码中出现此错误,我不太明白 THIS SOLUTION 如何应用于我的代码,因为我正在使用 Parse 云代码。我知道服务器是一个使用 javascript 运行 Parse 的 via,然后在数据库中运行 CRUD 操作。但是因为实际的 HTTP 请求并不能真正看到它,所以我不知道发生了什么以及我应该在哪里调整我的代码。

如果有人能指出我做错了什么以及如何调整我的代码,那就太好了。这也算大事吗?如果我将像下面这样的云代码留在生产中,这会很重要吗?使用此功能,现在一切都按照高级别的结果完美运行。

我认为我应该继续使用 .then() 函数。如果是这样的话,这棵树到底能走多久?

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 );
  );

【问题讨论】:

您提到的错误与尝试向同一个 http 请求发送多个响应有关,但是您没有在此代码中显示任何 http 响应的发送,所以我认为我们需要查看更多代码 - 理想情况下,它是整个请求处理程序的一部分。此外,这通常是来自 http 请求处理程序或快速路由处理程序的错误。我们需要完整地查看该处理程序。 这是有道理的,这绝对是我的问题的一部分,我不确定在使用 Parse 时如何获得它。当我得到处理程序时,我会调查并发布它。 所以,我根本不知道 Parse 系统。此代码中是否存在应该直接导致发送 http 响应的方法调用? 是的,每个调用都直接导致一个 HTTP 请求。我认为等待该功能会起作用,它确实有效,但也会引发错误......我已经解决了这个问题,请参阅下面的解决方案。现在发布。我认为在一个函数中包含许多 .then() 以执行许多操作是非常奇怪的...... 【参考方案1】:

您的原始代码并未等待您的所有承诺。相反,您混合使用了await.then(),但没有在任何地方正确控制流量。

当您将所有.then() 相互嵌套时,您能够正确地对所有异步操作进行排序,以便 B 等到 A 完成,C 等到 B 完成。您的原始代码没有这样做。

但是,您也可以像这样使用 await 完成所有这些操作,方法是在所有异步操作上使用 await 以确保您正在对所有内容进行排序:

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 );
);

【讨论】:

感谢您指出这一点。问题解决了,理解也增加了。 @RobbB - 这里的错误处理怎么样?如果您正在等待的任何承诺被拒绝怎么办? Parse 会抓住拒绝并做一些可以理解的事情吗?还是您必须抓住拒绝并采取适当的措施? 我目前正在检查我所有的云代码并处理可能的错误。最初我关心的是学习 javascript,现在是重构时间。【参考方案2】:

我不确定这是否是“javascript 正确”,但我将许多 .then() 链接在一起,并且不再出现错误。我不明白为什么我之前使用的 async/await 不起作用......但这解决了我的主要问题。

编辑:async/await 确实有效,但我在 Parse 日志中收到错误。

谁能更好地解释这一点?如果是这样,正确的答案仍然存在。

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);
            syncStatus.save(null,  useMasterKey: true ).then(function() 
                // 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 ).then(function() 
                    console.log("Save success");
                );
            );
        );
    );
);

【讨论】:

以上是关于将标头发送到客户端后无法设置标头-请帮助我在代码中理解这一点的主要内容,如果未能解决你的问题,请参考以下文章

将标头发送到客户端后无法设置标头-Nodejs + AWS-S3 getObject

节点 JS:错误 [ERR_HTTP_HEADERS_SENT]:在将标头发送到客户端后无法设置标头

Node.js,Express:将标头发送到客户端后无法设置标头

如何解决“将标头发送到客户端后无法设置标头”

GraphQL 突变“在将标头发送到客户端后无法设置标头”

节点js [ERR_HTTP_HEADERS_SENT]:将标头发送到客户端后无法设置标头