使用 mysql 和 node.js 中的承诺
Use mysql with promises in node.js
我刚刚关注了tutorial for authentication on node from scotch.io。
他们使用 mongodb 作为后端,我将其移植到 mysql。这是我第一个连接到数据库的节点应用程序。
我使用 bluebird promisify
config/database.js
中的 mysqljs/mysql
包
const mysql = require('mysql');
const Promise = require("bluebird");
Promise.promisifyAll(mysql);
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
这是我的 model/user.js
的代码:
const mysqlPool = require('../../config/database'),
bcrypt = require('bcrypt-nodejs'),
Promise = require("bluebird");
getDb = function(){
return mysqlPool.getConnectionAsync();
}
let user = {
create(user, done) {
getDb().then((db) => {
return db.queryAsync(`insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)`,
[user.name, user.token, user.type, user.external_id])
}).then((results, fields) => {
console.log(results, fields)
user.id = results.insertId
return done(null, user)
})
},
有些东西我觉得不好看:
getDb().then((db) => {
return db.queryAsync(...)
}).then(...)
看起来有点费解。我想要一个可以直接用作 db.queryAsync(...).then(...)
的变量 db
,但我无法找到如何将这样的承诺分配给变量 db
。
另外,我想就我的方法提出建议。这是在这里使用承诺的好方法还是有更好的方法?
是否有必要在 then
回调中 return done(null, user)
以遵守一般节点约定,或者在使用 promises (bluebird) 时是否不再需要?
您可以简单地 return 来自 user
模型的 create
方法的承诺。
create(user) {
return getDb().then((db) => {
return db.queryAsync(`insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)`,
[user.name, user.token, user.type, user.external_id])
}).then((results, fields) => {
console.log(results, fields)
user.id = results.insertId
return user;
})
},
此承诺随后将使用用户的值进行解析。因此,您可以在其他任何地方使用该方法 as
User.create(user)
.then(createdUser => { // do something with user here })
如果您可以访问最新版本的节点(任何高于 8 的版本),您可以使用 async-await
,使代码更易于理解。
async create(user) {
const db = await getDb();
const results = await db.queryAsync(`insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)`,
[user.name, user.token, user.type, user.external_id]);
user.id = results.insertId;
return user;
},
一个 async
函数可以像任何其他函数一样被调用,但它将 return 一个承诺,该承诺将以 returned 的值解析。所以方法的用法还是一样。
User.create(user)
.then(createdUser => { // do something with user here })
对于任何使用 promises 的工作最重要的建议是:放弃回调。
您的代码目前是回调 (done()
) 和承诺的混合体。不要那样做。专门使用承诺。 promises 的关键点是你可以 return 从你的异步函数中得到一些东西。您不需要依赖调用方传递的回调。
承诺所有 API。强调 return 事情。
const Promise = require("bluebird"),
mysqlPool = Promise.promisifyAll(require('../../config/database')),
bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));
let user = {
create: params => mysqlPool
.getConnectionAsync()
.then(db => db.queryAsync(
'insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)',
[params.name, params.token, params.type, params.external_id]
))
.then((results, fields) => ({
name: params.name,
token: params.token,
type: params.type,
external_id: params.external_id,
id: results.insertId
}))
};
请注意 user.create()
return 如何形成完整的价值链。 mySQL 连接变成查询结果变成新的用户对象。我不喜欢覆盖现有实例。避免副作用。
用法很简单。
user.create({
name: "foo",
token: 12345,
type: "user",
external_id: 67890
}).then(newUser => {
console.log(newUser);
}).catch(err => {
console.error(err);
});
现在至少有两个 npm 库可以通过 Promises 为节点提供对 MySQL 的访问:
node-mysql2 has its own "promise wrapper"
promise-mysql -“...mysqljs/mysql 的包装器,用 Bluebird promises 包装函数调用”
mysql2-promise - “...mysql2 的小承诺包装器,它是分叉的并与 mysql-promise 兼容”
我刚刚关注了tutorial for authentication on node from scotch.io。 他们使用 mongodb 作为后端,我将其移植到 mysql。这是我第一个连接到数据库的节点应用程序。
我使用 bluebird promisify
config/database.js
mysqljs/mysql
包
const mysql = require('mysql');
const Promise = require("bluebird");
Promise.promisifyAll(mysql);
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
这是我的 model/user.js
的代码:
const mysqlPool = require('../../config/database'),
bcrypt = require('bcrypt-nodejs'),
Promise = require("bluebird");
getDb = function(){
return mysqlPool.getConnectionAsync();
}
let user = {
create(user, done) {
getDb().then((db) => {
return db.queryAsync(`insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)`,
[user.name, user.token, user.type, user.external_id])
}).then((results, fields) => {
console.log(results, fields)
user.id = results.insertId
return done(null, user)
})
},
有些东西我觉得不好看:
getDb().then((db) => {
return db.queryAsync(...)
}).then(...)
看起来有点费解。我想要一个可以直接用作 db.queryAsync(...).then(...)
的变量 db
,但我无法找到如何将这样的承诺分配给变量 db
。
另外,我想就我的方法提出建议。这是在这里使用承诺的好方法还是有更好的方法?
是否有必要在 then
回调中 return done(null, user)
以遵守一般节点约定,或者在使用 promises (bluebird) 时是否不再需要?
您可以简单地 return 来自 user
模型的 create
方法的承诺。
create(user) {
return getDb().then((db) => {
return db.queryAsync(`insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)`,
[user.name, user.token, user.type, user.external_id])
}).then((results, fields) => {
console.log(results, fields)
user.id = results.insertId
return user;
})
},
此承诺随后将使用用户的值进行解析。因此,您可以在其他任何地方使用该方法 as
User.create(user)
.then(createdUser => { // do something with user here })
如果您可以访问最新版本的节点(任何高于 8 的版本),您可以使用 async-await
,使代码更易于理解。
async create(user) {
const db = await getDb();
const results = await db.queryAsync(`insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)`,
[user.name, user.token, user.type, user.external_id]);
user.id = results.insertId;
return user;
},
一个 async
函数可以像任何其他函数一样被调用,但它将 return 一个承诺,该承诺将以 returned 的值解析。所以方法的用法还是一样。
User.create(user)
.then(createdUser => { // do something with user here })
对于任何使用 promises 的工作最重要的建议是:放弃回调。
您的代码目前是回调 (done()
) 和承诺的混合体。不要那样做。专门使用承诺。 promises 的关键点是你可以 return 从你的异步函数中得到一些东西。您不需要依赖调用方传递的回调。
承诺所有 API。强调 return 事情。
const Promise = require("bluebird"),
mysqlPool = Promise.promisifyAll(require('../../config/database')),
bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));
let user = {
create: params => mysqlPool
.getConnectionAsync()
.then(db => db.queryAsync(
'insert into bot_users (name, token, type, external_id) values (?, ?, ?, ?)',
[params.name, params.token, params.type, params.external_id]
))
.then((results, fields) => ({
name: params.name,
token: params.token,
type: params.type,
external_id: params.external_id,
id: results.insertId
}))
};
请注意 user.create()
return 如何形成完整的价值链。 mySQL 连接变成查询结果变成新的用户对象。我不喜欢覆盖现有实例。避免副作用。
用法很简单。
user.create({
name: "foo",
token: 12345,
type: "user",
external_id: 67890
}).then(newUser => {
console.log(newUser);
}).catch(err => {
console.error(err);
});
现在至少有两个 npm 库可以通过 Promises 为节点提供对 MySQL 的访问:
node-mysql2 has its own "promise wrapper"
promise-mysql -“...mysqljs/mysql 的包装器,用 Bluebird promises 包装函数调用”
mysql2-promise - “...mysql2 的小承诺包装器,它是分叉的并与 mysql-promise 兼容”