我使用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,所以我认为这不是正确的方法。
谁能告诉我一个例子如何做到这一点?
答案 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);
})
};