use*_*486 25 mysql asynchronous node.js promise node-mysql
我有一个python背景,目前正在迁移到node.js. 由于其异步性质,我有问题调整到node.js.
例如,我试图从MySQL函数返回一个值.
function getLastRecord(name)
{
var connection = getMySQL_connection();
var query_str =
"SELECT name, " +
"FROM records " +
"WHERE (name = ?) " +
"LIMIT 1 ";
var query_var = [name];
var query = connection.query(query_str, query_var, function (err, rows, fields) {
//if (err) throw err;
if (err) {
//throw err;
console.log(err);
logger.info(err);
}
else {
//console.log(rows);
return rows;
}
}); //var query = connection.query(query_str, function (err, rows, fields) {
}
var rows = getLastRecord('name_record');
console.log(rows);
Run Code Online (Sandbox Code Playgroud)
经过一些阅读,我意识到上面的代码无法工作,我需要返回一个由于node.js异步性质的承诺.我不能像python一样编写node.js代码.如何转换getLastRecord()
为返回承诺以及如何处理返回的值?
事实上,我想要做的就是这样;
if (getLastRecord() > 20)
{
console.log("action");
}
Run Code Online (Sandbox Code Playgroud)
如何以可读的方式在node.js中完成?
我想看看在这种情况下如何使用bluebird实现promises.
Jos*_*ook 46
这会有点分散,请原谅我.
首先,假设此代码正确使用了mysql驱动程序API,这里有一种方法可以将其包装为使用本机承诺:
function getLastRecord(name)
{
return new Promise(function(resolve, reject) {
// The Promise constructor should catch any errors thrown on
// this tick. Alternately, try/catch and reject(err) on catch.
var connection = getMySQL_connection();
var query_str =
"SELECT name, " +
"FROM records " +
"WHERE (name = ?) " +
"LIMIT 1 ";
var query_var = [name];
connection.query(query_str, query_var, function (err, rows, fields) {
// Call reject on error states,
// call resolve with results
if (err) {
return reject(err);
}
resolve(rows);
});
});
}
getLastRecord('name_record').then(function(rows) {
// now you have your rows, you can see if there are <20 of them
}).catch((err) => setImmediate(() => { throw err; })); // Throw async to escape the promise chain
Run Code Online (Sandbox Code Playgroud)
所以有一点:你还有回调.回调函数只是函数,您可以通过其选择的参数在将来某个时候调用某些函数.所以函数参数xs.map(fn)
,(err, result)
节点中看到的函数以及promise结果和错误处理程序都是回调函数.这有点让人感到困惑的是人们将特定类型的回调称为"回调",(err, result)
在节点核心中使用的是所谓的"延续传递风格",有时被不喜欢它们的人称为"节点回调".
现在,至少(async/await最终会到来),无论你是否采用承诺,你几乎都会遇到回调问题.
此外,我会注意到承诺不是立即的,显然在这里很有帮助,因为你仍然有回调.承诺只有在你将它们与Promise.all
累积器结合起来时才能真正发挥作用Array.prototype.reduce
.但他们做有时会亮的,他们都值得我们学习.
我已修改您的代码以使用Q(NPM模块)承诺.我假设您在上面的代码段中指定的'getLastRecord()'函数正常工作.
您可以参考以下链接来获取Q模块
var q = require('q');
function getLastRecord(name)
{
var deferred = q.defer(); // Use Q
var connection = getMySQL_connection();
var query_str =
"SELECT name, " +
"FROM records " +
"WHERE (name = ?) " +
"LIMIT 1 ";
var query_var = [name];
var query = connection.query(query_str, query_var, function (err, rows, fields) {
//if (err) throw err;
if (err) {
//throw err;
deferred.reject(err);
}
else {
//console.log(rows);
deferred.resolve(rows);
}
}); //var query = connection.query(query_str, function (err, rows, fields) {
return deferred.promise;
}
// Call the method like this
getLastRecord('name_record')
.then(function(rows){
// This function get called, when success
console.log(rows);
},function(error){
// This function get called, when error
console.log(error);
});
Run Code Online (Sandbox Code Playgroud)
我是Node.js和承诺的新手.我正在寻找一些能够满足我需求的东西,这是我在结合我找到的几个例子之后最终使用的.我希望能够获取每个查询的连接并在查询完成后立即释放(querySql
),或者从池中获取连接并在Promise.using范围内使用它,或者在我想要它时释放它(getSqlConnection
).使用此方法,您可以一个接一个地连接多个查询而不嵌套它们.
db.js
var mysql = require('mysql');
var Promise = require("bluebird");
Promise.promisifyAll(mysql);
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
var pool = mysql.createPool({
host: 'my_aws_host',
port: '3306',
user: 'my_user',
password: 'my_password',
database: 'db_name'
});
function getSqlConnection() {
return pool.getConnectionAsync().disposer(function (connection) {
console.log("Releasing connection back to pool")
connection.release();
});
}
function querySql (query, params) {
return Promise.using(getSqlConnection(), function (connection) {
console.log("Got connection from pool");
if (typeof params !== 'undefined'){
return connection.queryAsync(query, params);
} else {
return connection.queryAsync(query);
}
});
};
module.exports = {
getSqlConnection : getSqlConnection,
querySql : querySql
};
Run Code Online (Sandbox Code Playgroud)
usage_route.js
var express = require('express');
var router = express.Router();
var dateFormat = require('dateformat');
var db = require('../my_modules/db');
var getSqlConnection = db.getSqlConnection;
var querySql = db.querySql;
var Promise = require("bluebird");
function retrieveUser(token) {
var userQuery = "select id, email from users where token = ?";
return querySql(userQuery, [token])
.then(function(rows){
if (rows.length == 0) {
return Promise.reject("did not find user");
}
var user = rows[0];
return user;
});
}
router.post('/', function (req, res, next) {
Promise.resolve().then(function () {
return retrieveUser(req.body.token);
})
.then(function (user){
email = user.email;
res.status(200).json({ "code": 0, "message": "success", "email": email});
})
.catch(function (err) {
console.error("got error: " + err);
if (err instanceof Error) {
res.status(400).send("General error");
} else {
res.status(200).json({ "code": 1000, "message": err });
}
});
});
module.exports = router;
Run Code Online (Sandbox Code Playgroud)
我对节点还是有点陌生,所以也许我错过了一些让我知道它是如何工作的东西。触发异步节点不会只是将其强加给您,因此您必须提前考虑并计划。
const mysql = require('mysql');
const db = mysql.createConnection({
host: 'localhost',
user: 'user', password: 'password',
database: 'database',
});
db.connect((err) => {
// you should probably add reject instead of throwing error
// reject(new Error());
if(err){throw err;}
console.log('Mysql: Connected');
});
db.promise = (sql) => {
return new Promise((resolve, reject) => {
db.query(sql, (err, result) => {
if(err){reject(new Error());}
else{resolve(result);}
});
});
};
Run Code Online (Sandbox Code Playgroud)
在这里,我像平常一样使用 mysql 模块,但我创建了一个新函数来提前处理 Promise,将其添加到 db const 中。(您在很多节点示例中将其视为“连接”。
现在让我们使用 Promise 调用 mysql 查询。
db.promise("SELECT * FROM users WHERE username='john doe' LIMIT 1;")
.then((result)=>{
console.log(result);
}).catch((err)=>{
console.log(err);
});
Run Code Online (Sandbox Code Playgroud)
我发现当您需要基于第一个查询执行第二个查询时,这很有用。
db.promise("SELECT * FROM users WHERE username='john doe' LIMIT 1;")
.then((result)=>{
console.log(result);
var sql = "SELECT * FROM friends WHERE username='";
sql = result[0];
sql = "';"
return db.promise(sql);
}).then((result)=>{
console.log(result);
}).catch((err)=>{
console.log(err);
});
Run Code Online (Sandbox Code Playgroud)
您实际上应该使用 mysql 变量,但这至少应该为您提供一个在 mysql 模块中使用 Promise 的示例。
此外,通过上述操作,您仍然可以在这些承诺范围内随时继续以正常方式使用 db.query,它们就像正常一样工作。
希望这对死亡三角有所帮助。
归档时间: |
|
查看次数: |
42351 次 |
最近记录: |