使用socket.io emit时,Express响应仍然存在

时间:2018-04-23 12:55:03

标签: node.js express socket.io

目前正在构建一个微服务应用程序。每个容器之间的通信是通过Web套接字进行的,网关是一个REST网关。

我希望能够在post请求中使用emit,这在目前正常工作。但是当套接字要处理on事件然后使用快速响应对象通过网关回复时,该对象不会被response.json调用关闭。该对象在同一路径内的另一个on事件内仍处于活动状态,然后使新请求生成错误headers cannot be set after they are send。这是有道理的,但我如何确保新请求获得新的响应对象?

第一次请求
网关 - > (ws) - >微服务器 - > (ws) - >网关 - > (http)用户
第二次请求
网关 - > (ws) - >微服务器 - > (ws) - >网关 - > ERROR

网关摘要

app.post("/api/user/create", function (req, res) {
  console.log("Create request");
  let token = req.get("Authentication");
  let userData = req.body;
  ioClientUsers.emit("create", {
    "token": token,
    "userData": userData
  });
  ioClientUsers.once("user created", success => {
    console.log(res.headersSent);
    if (success) {
      return res.json({
        "status": "created"
      }); 
    } else {
      return res.json({
        "status": "not created"
      });
    }
  });
  ioClientUsers.once("user not created", () => {
    console.log(res.headersSent);
    res.json({
      "status": "not created"
    });
  });
});

微服务代码段

 socket.on("create", createObj => {
 console.log(createObj);
 userController.createUser(createObj.token, createObj.userData, (err, success) => {
   console.log(err, success);
   if (err) {
     socket.emit("user not created");
   } else {
     socket.emit("user created", success);
   }
 });
});

修改 只是再次发布,以便如果其他人有同样的问题,那么对此或该编辑的答案可以解决问题:

 app.post("/api/user/create", function (req, res) {
  let token = req.get("Authentication");
  let userData = req.body;
  ioClientUsers.emit("create", {
    "token": token,
    "userData": userData
  });
  ioClientUsers.once("user created", userCreated);
  ioClientUsers.once("user not created", userNotCreated);

  function userCreated(success){
    if (success) {
      res.json({
        "status": "created"
      }); 
    } else {
      res.json({
        "status": "not created"
      });
    }  
    rmListner();
  }
  function userNotCreated(){
    console.log(res.headersSent);
    res.json({
      "status": "not created"
    });
    rmListner();
  }

  function rmListener(){
    ioClientUsers.removeListener("user created", userCreated);
    ioClientUsers.removeListener("user not created", userNotCreated);
  }
});

1 个答案:

答案 0 :(得分:1)

我会做这样的事情

app.post("/api/user/create", function (req, res) {
  console.log("Create request");
  let token = req.get("Authentication");
  let userData = req.body;
  ioClientUsers.emit("create", {
    "token": token,
    "userData": userData
  });

  function createdCallback(success) {
    if (success) {
      sendStatus('created')
    } else {
      sendStatus('not created')
    }
  }

  function notCreatedCallback() {
    sendStatus('not created')
  }

  function sendStatus(status) {
    console.log(res.headersSent);
    // UNSUBSCRIBE YOUR LISTENERS HERE
    ioClientUsers.removeListener("user created", createdCallback);
    ioClientUsers.removeListener("user not created", notCreatedCallback);
    res.json({'status': status})
  }

  ioClientUsers.once("user created", createdCallback);
  ioClientUsers.once("user not created", notCreatedCallback);
});

在调用res.json之前,所有套接字侦听器都被删除。看看是否有效。