节点postgres同步/异步查询通过相同的方法

时间:2019-01-15 22:50:44

标签: javascript node.js async-await synchronization pg

我使用的是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();
                })
        })
    }        
}

0 个答案:

没有答案