未能在我的 websocket 确认重新连接逻辑中解决承诺

Failing to resolve promise within my websocket acknowledgement reconnect logic

我有一个自定义连接函数,它创建了一个承诺,一旦我发出 websocket 调用并收到确认,我就想解决这个问题。远程服务器可能已启动,也可能已关闭,但如果它不可用,我想继续尝试直到成功。

const socketIOClient = require('socket.io-client');

function createTimeoutCallback(callback)
{
  let called = false;

  let timerID = setTimeout(() => {
      if (called) return;
      called = true;
      callback(new TimeoutError());
    },
    60*1000);

  return function() {
    if (called) return;
    called = true;
    clearTimeout(timerID);
    callback.apply(this, arguments);
  }
}

async function myConnect()
{
  let mysocket = socketIOClient(url);

  return new Promise((resolve, reject) => {

    mysocket.emit('clientconnect', args, createTimeoutCallback((resp) => {
      if (!(resp instanceof TimeoutError)) {

        // SUCCESS
        doSomething();
        resolve();
      }

      // We timed out, try again
      else {
        mysocket.close();
        setTimeout(myConnect, 60*1000);
      }  
    }));
  });
}

await connect();
// doSomething() gets called but we never get here

在上面的代码中,如果端点可用,则一切正常。但是当 (1) 我等待它的承诺时,我永远不会从 myConnect() 函数返回; (2) 该功能需要进行多次连接尝试(例如,服务器最初未启动); (3) 端点终于重新上线,连接成功。我怀疑这与我在重新连接尝试时放弃最初的承诺有关,但我不想拒绝它,否则操作会过早失败。

我确实找到了一个解决方法,它依赖于一个嵌入式函数。使用这种技术,只有一个始终可访问且在范围内的承诺,并且基于计时器的递归(即,不是基于堆栈的)始终包含在永不放弃的单个承诺中。我在 Jaromanda 回答之前将其放在一起,所以我无法确认他的解决方案是否有效。

async function myConnect()
{
  return new Promise((resolve, reject) => {

    function innerConnect()
    {
      let mysocket = socketIOClient(url);

      mysocket.emit('clientconnect', args, createTimeoutCallback((resp) => {
        if (!(resp instanceof TimeoutError)) {

          // SUCCESS
          doSomething();
          resolve();
        }

        // We timed out, try again
        else {
          mysocket.close();
          setTimeout(innerConnect, 60*1000);
        }  
      }));
    }

    innerConnect();
  });
}