为什么queryAsync()会导致添加元数据?
我使用queryAsync()
按问题的答案规定,它的工作原理,但它增加了很多额外的元数据到我的查询结果,否则是一个简单的查询。
以下是我用来处理/执行查询并logging结果的内容:
var retrieveSettings = Promise.method(function (username, connection) { console.log('User ' + username + ' retrieving settings...'); var q = 'select * from sales_settings'; return connection.queryAsync(q).then(function (rows, fields) { list = []; for (x = 0; x < rows.length; x++) { list.push(rows[x]); } //console.log('Settings: ' + JSON.stringify(list, null, 4)); return list; }); });
这里是logging的结果:
Settings: [ [ { "group_name": "add_auto", "commission_rate": 0, "monthly_req": 0, "category_name": "Auto", "commission_type": "none", "group_title": "Added Auto" }, { "group_name": "add_fire", "commission_rate": 0, "monthly_req": 0, "category_name": "Fire", "commission_type": "none", "group_title": "Added Fire" }, { "group_name": "bank_dep", "commission_rate": 25, "monthly_req": 0, "category_name": "Bank", "commission_type": "static", "group_title": "Bank Deposit" }, { "group_name": "bank_loan", "commission_rate": 75, "monthly_req": 8, "category_name": "Bank", "commission_type": "static", "group_title": "Bank Loan" }, { "group_name": "health", "commission_rate": 0.084, "monthly_req": 4, "category_name": "Health", "commission_type": "premium", "group_title": "Health App" }, { "group_name": "life", "commission_rate": 0.084, "monthly_req": 8, "category_name": "Life", "commission_type": "premium", "group_title": "Life App" }, { "group_name": "new_auto", "commission_rate": 0.03, "monthly_req": 32, "category_name": "Auto", "commission_type": "rate", "group_title": "Raw New Auto" }, { "group_name": "new_fire", "commission_rate": 0.03, "monthly_req": 20, "category_name": "Fire", "commission_type": "rate", "group_title": "Raw New Fire" } ], [ { "catalog": "def", "db": "officeball", "table": "sales_settings", "orgTable": "sales_settings", "name": "group_name", "orgName": "group_name", "filler1": [ 12 ], "charsetNr": 33, "length": 135, "type": 253, "flags": 20483, "decimals": 0, "filler2": [ 0, 0 ], "zeroFill": false, "protocol41": true }, { "catalog": "def", "db": "officeball", "table": "sales_settings", "orgTable": "sales_settings", "name": "commission_rate", "orgName": "commission_rate", "filler1": [ 12 ], "charsetNr": 63, "length": 13, "type": 246, "flags": 4097, "decimals": 3, "filler2": [ 0, 0 ], "zeroFill": false, "protocol41": true }, { "catalog": "def", "db": "officeball", "table": "sales_settings", "orgTable": "sales_settings", "name": "monthly_req", "orgName": "monthly_req", "filler1": [ 12 ], "charsetNr": 63, "length": 11, "type": 3, "flags": 4097, "decimals": 0, "filler2": [ 0, 0 ], "zeroFill": false, "protocol41": true }, { "catalog": "def", "db": "officeball", "table": "sales_settings", "orgTable": "sales_settings", "name": "category_name", "orgName": "category_name", "filler1": [ 12 ], "charsetNr": 33, "length": 135, "type": 253, "flags": 4097, "decimals": 0, "filler2": [ 0, 0 ], "zeroFill": false, "protocol41": true }, { "catalog": "def", "db": "officeball", "table": "sales_settings", "orgTable": "sales_settings", "name": "commission_type", "orgName": "commission_type", "filler1": [ 12 ], "charsetNr": 33, "length": 135, "type": 253, "flags": 4097, "decimals": 0, "filler2": [ 0, 0 ], "zeroFill": false, "protocol41": true }, { "catalog": "def", "db": "officeball", "table": "sales_settings", "orgTable": "sales_settings", "name": "group_title", "orgName": "group_title", "filler1": [ 12 ], "charsetNr": 33, "length": 72, "type": 253, "flags": 4097, "decimals": 0, "filler2": [ 0, 0 ], "zeroFill": false, "protocol41": true } ] ]
为什么这个不寻常的元数据被添加到我的查询结果?
从mysql的query()
返回的标准callback既返回rows
又返回fields
。 你正在使用的asynchronous包装(例如,如果你Q.denodeify()
)只返回一个单一的东西,所以对于具有多个参数的callback,在这种情况下[rows,fields]
返回一个[param1,param2]
的数组。
与此相关的是,你内部的函数只需要接受一个参数(这就是[rows,fields]的这个数组)。
看到我对这个问题的答案的第二部分作为一个例子。
你的代码应该是这样的:
var retrieveSettings = Promise.method(function (username, connection) { console.log('User ' + username + ' retrieving settings...'); var q = 'select * from sales_settings'; return connection.queryAsync(q).then(function (results) { var rows = results[0]; // get the rows var fields = results[1]; // don't really care, but just for illustration list = []; for (x = 0; x < rows.length; x++) { list.push(rows[x]); } //console.log('Settings: ' + JSON.stringify(list, null, 4)); return list; }); });
而实际上,对于上面的代码,没有理由你的整个callback不能只是:
return connection.queryAsync(q).then(function (results) { return results[0]; // get the rows });
看起来你正在使用蓝鸟,在这种情况下,你可以使用.spread
:
var retrieveSettings = Promise.method(function (username, connection) { console.log('User ' + username + ' retrieving settings...'); var q = 'select * from sales_settings'; return connection.queryAsync(q).spread(function (rows, fields) { list = []; for (x = 0; x < rows.length; x++) { list.push(rows[x]); } //console.log('Settings: ' + JSON.stringify(list, null, 4)); return list; }); });
mysql模块的问题在于它不符合节点js的callback标准(err, result)
。 相反,它使用(err, result1, result2)
。 由于函数只能抛出一个exception或返回一个值,蓝鸟会返回一个[result1, result2]
的数组,以避免信息丢失。
.spread
就像.spread
.then
除非它假定实现值是一个数组,并将数组的值传递给参数。