node-postgres声明如下:
node-postgres同时支持"事件发射器"样式API和"回调"样式。这 回调样式更简洁,通常首选,但事件 API 可以进来 方便。它们可以混合搭配。
使用事件发射器 API,我可以执行以下操作:
var db = new pg.Client("insert-postgres-connection-info");
db.connect();
然后,我可以使用db
通过db.query('sql statement here')
在整个 Web 应用程序中执行查询。使用回调样式,每次我想运行查询时,我都会执行以下操作:
pg.connect(conString, function(err, client) {
client.query("sql statement", function(err, result) {
// do stuff
});
});
所以我的问题是为什么"通常首选"使用回调样式?每次对数据库执行某些操作时打开连接不是效率低下吗?使用回调样式有什么好处?
编辑
我可能会误解他所说的"回调风格"是什么意思(我不是在开玩笑,我的 JavaScript 不是很强大),但我的问题是关于连接方法的。我假设以下是回调样式的连接方法:
// Simple, using built-in client pool
var pg = require('pg');
//or native libpq bindings
//var pg = require('pg').native
var conString = "tcp://postgres:1234@localhost/postgres";
//error handling omitted
pg.connect(conString, function(err, client) {
client.query("SELECT NOW() as when", function(err, result) {
console.log("Row count: %d",result.rows.length); // 1
console.log("Current year: %d", result.rows[0].when.getYear());
});
});
以下是事件发射器 API 连接方法:
// Evented api
var pg = require('pg'); //native libpq bindings = `var pg = require('pg').native`
var conString = "tcp://postgres:1234@localhost/postgres";
var client = new pg.Client(conString);
client.connect();
如果我只是在这里混淆了术语,我的问题仍然存在。 pg.connect(do queries)
每次使用时都会打开一个新连接(不是吗? 而
var client = new pg.Client(conString);
client.connect();
打开连接,然后允许您在必要时使用 client
运行查询,不是吗?
EventEmitter 样式更适合这种类型的事情:
var query = client.query("SELECT * FROM beatles WHERE name = $1", ['John']);
query.on('row', function(row) {
console.log(row);
console.log("Beatle name: %s", row.name); //Beatle name: John
console.log("Beatle birth year: %d", row.birthday.getYear()); //dates are returned as javascript dates
console.log("Beatle height: %d' %d"", Math.floor(row.height/12), row.height%12); //integers are returned as javascript ints
});
通过混合和匹配,您应该能够执行以下操作:
// Connect using EE style
var client = new pg.Client(conString);
client.connect();
// Query using callback style
client.query("SELECT NOW() as when", function(err, result) {
console.log("Row count: %d",result.rows.length); // 1
console.log("Current year: %d", result.rows[0].when.getYear());
});
请注意,即使使用回调样式,也不会在每次要执行查询时都打开连接;最有可能的是,您会在应用程序启动时打开连接并始终使用它。
有利有弊,您选择的一个取决于您的用例。
用例 1:将结果集逐行返回给客户端。
如果要将数据返回到客户端的方式与从数据库中返回数据的方式大致相同 - 逐行 - 那么您可以使用事件发射器样式来减少延迟,我在这里将其定义为发出请求和接收第一行之间的时间。如果改用回调样式,则延迟会增加。
用例 2:基于整个结果集返回分层数据结构(例如 JSON)。
如果要以分层数据结构(如 JSON)将数据返回到客户端(当结果集是层次结构的平面表示形式时,这样做是为了节省带宽),则应使用回调样式,因为在收到所有行之前无法返回任何内容。您可以使用事件发射器样式并累积行(node-postgres提供了这样的机制,因此您不必通过查询维护部分构建结果的映射),但这将是毫无意义的浪费精力,因为您无法返回任何结果直到您收到最后一行。
用例 3:返回分层数据结构数组。
返回分层数据结构数组时,如果使用回调样式,您将有很多行需要一次完成所有行。这会阻塞相当长的时间,这并不好,因为您只有一个线程为许多客户端提供服务。因此,您应该将事件发射器样式与行累加器一起使用。结果集的排序应为,当您检测到特定字段的值发生变化时,您知道当前行表示要返回的新结果的开始,并且到目前为止累积的所有内容都表示现在完整的结果,您可以将其转换为分层形式并返回到客户端。