【问题标题】:Best practice for running a background process in Node?在 Node 中运行后台进程的最佳实践?
【发布时间】:2021-08-20 05:09:45
【问题描述】:

比如说我有下面的代码,一个简单的 UI 测试。

async function testMyCoolUI() {
  await uiFramework.openMyApp(url);
      
  await sleep(2000);
    
  await uiFramework.clickButtonX();

  await uiFramework.clickButtonY();
}

现在添加了一个新要求。在测试期间的任何点,屏幕上可能会弹出一个窗口说“你是机器人吗?”,我们必须选择“否”。

您将如何构建您的测试,以使该“进程”可以在测试的后台持续运行,并注意此弹出窗口?我最初的想法是启动一个异步函数轮询弹出窗口,但不要等待testMyCoolUI 中的承诺。

async function testMyCoolUI() {
  await uiFramework.openMyApp(url);
      
  await sleep(2000);

  startPollingForPopup(); // this is an async function, but not waiting on it
    
  await uiFramework.clickButtonX();

  await uiFramework.clickButtonY();
}

但是这感觉不对,承诺将无法解决,并且流程不会很好地清理。在 JS 中“正确”执行此操作的方法是什么?

其他想法:

Promise.all([testMyCoolUI, pollForPopup]);

但在这种情况下,测试仍将在轮询解决之前完成。出于同样的原因,Promise.race 在这里也不起作用。

【问题讨论】:

    标签: javascript node.js asynchronous async-await


    【解决方案1】:

    promise disposer pattern 是一种确保正确清理的良好代码结构模式:

    async function testMyCoolUI() {
      await uiFramework.openMyApp(url); 
      await sleep(2000);
      await withPollingForPopup(async () => {
        await uiFramework.clickButtonX();
        await uiFramework.clickButtonY();
      });
    }
    
    async function withPollingForPopup(run) {
      try {
        startPollingForPopup(); // not waiting for anything
        return await run();
      } finally {
        stopPollingForPopup(); // optionally `await` it
      }
    }
    

    这假定一个后台进程,可能是一个事件订阅,可以启动和停止。

    或者,如果后台进程确实返回了一个拒绝错误的承诺并且您想尽快中止,您可以使用

    async function withPollingForPopup(run) {
      const poll = runPollingForPopup();
      const [res] = await Promise.all([
        run().finally(poll.stop),
        poll.promise
      ]);
      return res;
    }
    

    【讨论】:

    • 这很棒。以前在代码中看到过这一点,但不知道这种模式。直到。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2010-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多