【问题标题】:Unable to resolve a promise in a socket.io callback无法解决 socket.io 回调中的承诺
【发布时间】:2019-07-08 10:19:23
【问题描述】:

我正在创建一个递归系统,它重新发送 socket.io 数据包,直到服务器通过完成 socket.io 确认来回答。我创建了一个承诺,它将在 X 秒内拒绝或解决如果服务器及时回答,如果它超时,我会重新创建一个超时时间更长的承诺。

问题是当之前至少有一次超时时,确认无法解决承诺,我不明白为什么。

这是我的代码的 sn-p :

  async emit(event, data) {
    if (!this.socket) {
      this.eventToSend[event] = data;
    }

    let timeoutRef;
    let alreadyResolved = false;

    return new Promise(async r => {

      const sentPromise = timeout => {
        return new Promise((resolve, reject) => {
          console.log("------ New Call ------");
          timeoutRef = setTimeout(() => {
            if (alreadyResolved === true) {
              console.log("Promise with timeout : " + timeoutRef + " is already resolved !!!");
            } else {
              console.log("promise " + timeoutRef + " timeouted !");
              reject();
            }
          }, timeout);
          console.log("Create promise with Timeout number : " + timeoutRef);

          this.socket.emit(event, { data }, function(response) {
            alreadyResolved = true;
            console.log("try to delete " + timeoutRef + " timeout");
            resolve(response);
          });
        });
      };

      try {
        const result = await this.recursiveSend(sentPromise);
        console.log("received the result " + result + ", aborting the process");
        r(result);
      } catch (e) {
        console.error(e);
        this.socket.disconnect(true);
      }
    });
  }

  async recursiveSend(promise, retryIndex = 0) {
    try {
      const result = await promise(this.timeoutRate[retryIndex]);
      console.log("recevied result ! " + result);
      return result;
    } catch (e) {
      // Here the setTimeout executed before I received the server acknowledgement
      const newRetryIndex = retryIndex + 1;
      if (newRetryIndex >= this.timeoutRate.length) {
        throw new Error("Timeout exceeded, unable to join the socket");
      } else {
        return this.recursiveSend(promise, newRetryIndex);
      }
    }
  }

这是实际的控制台日志输出:

...  
------ New Call ------  
Create promise with Timeout number : 32  
promise 32 timeouted !  
------ New Call ------  
Create promise with Timeout number : 34  
promise 34 timeouted !  
------ New Call ------  
Create promise with Timeout number : 36  
try to delete 36 timeout // Here the promise is supposed to be resolved  
Promise with timeout : 36 is already resolved !!! // But here we tried to reject it  

日志不可靠,所以我尝试使用断点,我仍然先进入resolve()(但我无法进入),然后进入reject()。这就像 socket.io 确认是在另一个线程中进行的,但是当没有超时并且服务器立即响应时它可以完美运行

【问题讨论】:

  • 究竟何时调用this.socket.emit 的回调?您是否在“旧”发出回调中得到确认,而不是在重试中得到确认?
  • 我删除了异步函数并简单地返回了promise,似乎它没有改变任何东西......服务器在收到第一个请求后6秒响应。我不明白你的最后一个问题,确认只在最后一个电话中收到
  • 你怎么知道这是最后一个电话?您的 timeoutRefalreadyResolved 变量是全局变量。尝试将他们的声明放在sentPromise 函数中。
  • 所以您说您没有收到“recevied result !”和“received the result ... aborting the process”日志,但希望他们?

标签: javascript node.js promise socket.io settimeout


【解决方案1】:

传递给recursiveSend 的Promise 在超时时是rejected,之后相同的Promise 再次在catch 中传递给recursiveSend,您正在尝试resolve 它。

解决已被拒绝的 Promise 是不可能的。

【讨论】:

  • 我不确定它是否是同一个承诺,因为它是一个创建一个在递归调用中传递的新函数的函数。我每次都awaitnew Promise。这里的问题是,确认回调中的解析是创建的第一个承诺的解析。所以当我的服务器响应时,回调会在一个已经被拒绝的承诺中执行。我只是通过存储外部创建的最后一个 resolve 函数并调用它而不是第一个来解决它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
  • 2018-10-08
  • 2014-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多