几秒钟后超时 async/await 函数

时间:2021-02-18 15:28:40

标签: javascript typescript async-await node-oracledb

我使用oracledb创建了一个获取Oracle连接的函数,但在少数情况下,即使他没有获得连接,oracledb也没有抛出异常,显然他试图无限连接。

const getConnection = async (): Promise<oracledb.Connection | undefined> => {
  let connection;

  try {
    connection = await oracledb.getConnection({
      user: process.env.DB_LOGIN,
      password: process.env.DB_PASSWORD,
      connectString: process.env.DB_STRING_CONNECTION,
    });
  } catch (err) {
    console.error(err);
  }
  return connection;
};

我看到一些使用 Promise.racing 和 setTimeout 的示例,但我无法将其付诸实践,我的尝试总是在控制台上得到 UnhandledPromiseRejectionWarning,所以我认为这不是正确的方法。

谁能告诉我一个例子如何做到这一点?

3 个答案:

答案 0 :(得分:2)

您似乎可以在 connectString 上设置超时:

<块引用>

使用 Oracle Client 19c,可以在 Easy Connect 字符串中传递超时,例如在 15 秒后超时:“mydbmachine.example.com/orclpdb1?connect_timeout=15”

http://oracle.github.io/node-oracledb/doc/api.html#dbcalltimeouts

这意味着您可以简单地构造带有超时的字符串:

connectString: process.env.DB_STRING_CONNECTION + '?connect_timeout=15',

当然有更好的方法来处理字符串的构造。

您可以使用这种连接字符串格式来指定没有 19c 客户端的超时时间:

(DESCRIPTION=(CONNECT_TIMEOUT=15 ms)(ADDRESS=(PROTOCOL=TCP)(HOST=mymachine.example.com)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))(RETRY_COUNT=3)

(也是链接文档的一部分)

答案 1 :(得分:2)

CertainPerformance 的回答很好,但是我建议不要将超时逻辑与您的函数纠缠在一起。这些是通用的东西,应该与您的连接逻辑分开实现。

我认为下面的方法很好,因为 timeout 可由调用者配置,允许他们决定任务应该等待多长时间。

const sleep = ms =>
  new Promise(r => setTimeout(r, ms))

const timeout = (p, ms) =>
  Promise.race([
    p,
    new Promise((_, r) => sleep(ms).then(_ => r(Error("timeout"))))
  ])
  
const fakeConnect = () =>
  sleep(2000).then(_ => "connected!")


// Example 1: 500 ms timeout
timeout(fakeConnect(), 500)
  .then(console.log, console.error)  // Error: timeout

  
// Example 2: 10 second timeout
timeout(fakeConnect(), 10000)        // connected!
  .then(console.log, console.error)

答案 2 :(得分:1)

Promise.race 如果正确实施它应该可以正常工作。将 getConnection 与解决(而非拒绝)的 Promise 竞争,并确保链接到 .catch

const getConnection = (): Promise<oracledb.Connection | undefined> => {
    return Promise.race([
        oracledb.getConnection({
            user: process.env.DB_LOGIN,
            password: process.env.DB_PASSWORD,
            connectString: process.env.DB_STRING_CONNECTION,
        }),
        new Promise((resolve) => { setTimeout(resolve, 5000); })
    ])
        .catch((error) => {
            // this will only be entered into if getConnection rejects (and not if it times out)
            console.log(error);
        })
};