在异步功能(Node.js / ES6)中的while循环中等待

时间:2019-12-02 16:35:05

标签: node.js typescript async-await

我正在编写Windows Node.js服务器应用程序(使用ES6 btw)。

我要做的第一件事-在顶层代码中-坐在while循环中,调用一个异步函数来搜索特定的注册表项/值。此函数经过“验证”-如果找到则返回值数据,否则抛出:

async GetRegValue(): Promise<string> { ... }

我需要坐在while循环中,直到注册表项存在,然后获取值数据。 (重试之间有延迟)。 我想我知道如何等待异步调用完成(一种方式或另一种方式),然后再进行其余的启动工作,但我不知道如何坐在循环中等待它完成成功

请问关于如何实现这一目标的任何建议? (我对打字稿还不是很陌生,但仍在努力解决所有异步/等待情况!)

谢谢

编辑

谢谢大家。我知道我对自己的代码“含糊不清”-我不想提出我的真实/伪代码尝试,因为它们都可能忽略了您可以希望帮助我理解的要点。 因此,我只是将其保留为文本描述...尽管我会尝试:

async GetRegValue(): Promise<string> {

    const val: RegistryItem = await this.GetKeyValue(this.KEY_SW, this.VAL_CONN);
    return val.value
}

private async GetKeyValue(key: string, name: string): Promise<RegistryItem> {

    return await new Promise((resolve, reject) => {
        new this.Registry({
            hive: this.Hive, key
        }).get(name, (err, items) => {

            if (err) {
                reject(new Error('Registry get failed'));
            }
            else {
                resolve( items );
            }
        });
    })
        .catch(err => { throw err });
}

所以我想做类似的事情:

let keyObtained = false
let val
while (keyObtained == false)
{
    // Call GetRegValue until val returned, in which case break from loop
    // If exception then pause (e.g. ~100ms), then loop again
    }
}

// Don't execute here till while loop has exited

// Then use 'val' for the subsequent statements

正如我所说的,GetRegValue()在我使用它的其他地方也能正常工作,但是在这里我试图暂停进一步的执行(并重试),直到它返回一个值为止

2 个答案:

答案 0 :(得分:0)

您可能只可以使用递归。这是一个示例,说明如何使用下面的GetRegValue函数继续调用retryReg函数直到问题解决。

如果碰到了捕获盒,它将反复调用GetRegValue直到成功解决。

您应该在catch()中添加一个计数器,如果您尝试了x次放弃操作,就会在其中添加计数器。

请记住,我嘲笑了整个GetRegValue函数,但是鉴于您所说的,它仍然对您有用。

let test = 0;

function GetRegValue() {
  return new Promise((resolve, reject) => {
    setTimeout(function() {
      test++;

      if (test === 4) {
        return resolve({
          reg: "reg value"
        });
      }

      reject({
        msg: "not ready"
      });

    }, 1000);
  });
}

function retryReg() {
  GetRegValue()
    .then(registryObj => {
      console.log(`got registry obj: ${JSON.stringify(registryObj)}`)
    })
    .catch(fail => {
      console.log(`registry object is not ready: ${JSON.stringify(fail)}`);
      retryReg();
    });
}

retryReg();

答案 1 :(得分:0)

我不明白您为什么需要此行:

.catch(err => { throw err });

在这种情况下,while的循环条件没有多大用处,因为您实际上并不需要状态变量或表达式来确定循环是否应该继续:

let val;
while (true)
{
    try {
       val = await GetRegValue(/* args */);
       break;

    } catch (x) {
        console.log(x); // or something better
    }

    await delay(100);
}

如果对val的赋值成功,我们将其赋给break;语句,因此我们成功地退出了循环。否则,我们跳到catch块并记录错误,等待100毫秒,然后重试。

使用for循环可能会更好,因此对重试次数设置合理的限制。

请注意,npm package of the same name中有delay。大致与:

await new Promise(res => setTimeout(res, 100));