首页 > 解决方案 > 如何修复 HTTP 请求上的 setTimeout 行为?

问题描述

在我的客户端应用程序中,我使用 Socket IO 来检查未读事件。我向我的后端发出一个请求,它将超时设置为 5 秒,然后继续检查未读事件并发送回任何事件。

// client
socket.on("response", ({ mostRecentMessages }) => {
    // do some stuff first
    socket.emit("listenForNew", { userId, currentMessagesFromEveryone });
})
// backend
  socket.on("listenForNew", ({ userId, currentMessagesFromEveryone }) => {
    if (currentMessagesFromEveryone && userId) {
      const { MostRecentMessages } = require("./constants/models");

      const filteredIds = [];

      currentMessagesFromEveryone.forEach(message => {
        filteredIds.push(message.conversation._id);
      });

      console.log("Entered!");

      setTimeout(async () => {
        const mostRecentMessages = await MostRecentMessages.find({
          to: userId,
          date: { $gt: connectedUsersAllMessages[userId].timeIn },
          conversation: { $nin: filteredIds }
        }).populate("to from conversation");

        allMessagesSocket.sockets.connected[
          connectedUsersAllMessages[userId].socketId
        ].emit("response", {
          mostRecentMessages
        });
      }, 5000);
    }
  });

起初,它工作正常。它为大约 4、5 个请求打印Entered!一次。然后在 6 日,它开始打印Entered!两次。

为什么会发生这种情况,我做错了什么?

标签: javascriptnode.jsexpresssocket.io

解决方案


我赞成以下方法:

  • 等待 X 秒(在我们的用例中为 5 秒)
  • 调用异步操作(执行时间未知)
  • 等到异步执行完成
  • 在执行下一个调用之前再等待 X 秒

实现可能是这样的:

const interval = 5000;

function next() {
  setTimeout(async () => myAsyncOperation(), interval);
}

function myAsyncOperation() {
   const mostRecentMessages = await MostRecentMessages.find({
      to: userId,
      date: { $gt: connectedUsersAllMessages[userId].timeIn },
      conversation: { $nin: filteredIds }
    }).populate("to from conversation");

    allMessagesSocket.sockets.connected[
      connectedUsersAllMessages[userId].socketId
    ].emit("response", () => {
      mostRecentMessages();
      next(); // "next" function call should be invoked only after "mostRecentMessages" execution is completed (or a race condition may be applied)
    }); 
}

next();

我还没有编译这段代码,但我希望这个概念很清楚


推荐阅读