我使用的是pg软件包,我想准备一种根据是否发送了回调方法对数据库进行同步或异步查询的方法。
现在,我创建了以下脚本:
const { Pool } = require('pg');
module.exports = function(options) {
const pool = new Pool(options);
var typeStr = (obj) => ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
var prepareArgs = (args) => {
let callback = false,
query = {
text: "",
values: []
};
var argLen = args.length;
while (argLen--) {
let arg = args[argLen],
type = typeStr(arg);
switch (type) {
case "string": query.text = arg; break;
case "array": query.values = arg; break;
case "object": query = arg; break;
case "function": callback = arg; break;
}
}
return callback
? [query, callback]
: [query.text, query.values] ;
}
this.query = function() {
var args = prepareArgs(arguments);
console.log("args", args);
if (typeStr(args[0]) == "string") { // sync
return (async () => {
const client = await pool.connect()
try {
const res = await client.query.apply(client, args);
return res.rows;
} finally {
client.release()
}
})()
} else { // async
pool.connect().then(client => {
return client.query(args[0])
.then(args[1])
.then(res => {
client.release();
})
})
}
}
}
当我不发送回调函数时,我无法同步返回获取的行。
这是我的测试代码:
console.log("START")
let query = {
text: "SELECT value FROM public.settings WHERE key=$1::text",
values: ["index"]
}
let cbfn = (res) => { console.log("async", res.rows)}
db.query(query, cbfn);
var rows = db.query(query)
console.log("sync", rows)
console.log("FINISH")
在这种情况下,我希望在控制台中看到
开始
同步[...]
完成
异步[...]
但是实际结果就像
开始
同步Promise {}
完成
异步[...]
如果我将 cbfn 作为第三个参数传递,我希望在控制台末尾看到 async 日志。除了同步结果,一切似乎都还可以!
我还尝试将 query 函数转换为异步函数并更改测试代码
(async () => {
console.log("START")
let query = {
text: "SELECT value FROM public.settings WHERE key=$1::text",
values: ["index"]
}
let cbfn = (res) => { console.log("async", res.rows)}
db.query(query, cbfn);
var rows = await db.query(query)
console.log("sync", rows)
console.log("FINISH")
})()
现在控制台输出为
开始
异步[...]
同步[...]
完成
看起来像异步查询,就像同步!
有什么方法可以使这种方法起作用?
解决方案:
我发现了deasync包裹
query = function() {
var args = prepareArgs(arguments),
isSync = typeStr(args[0]) == "string";
if (isSync) { // sync
let rows;
(async () => {
const client = await pool.connect();
try {
const res = await client.query.apply(client, args);
rows = res.rows;
} finally {
client.release();
}
})()
while (rows === undefined) require('deasync').sleep(10);
return rows;
} else { // async
pool.connect().then(client => {
return client.query(args[0])
.then(args[1])
.then(res => {
client.release();
})
})
}
}