在node.js中使用带有promises的mysql

时间:2018-01-06 16:31:36

标签: mysql node.js promise node-mysql

我刚跟着tutorial for authentication on node from scotch.io。 他们使用mongodb作为后端,我把它移植到mysql。这是我第一个连接数据库的节点应用程序。

我在promisify

中使用bluebird mysqljs/mysql config/database.js个包
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我可以直接用作db.queryAsync(...).then(...),但我无法找到如何将这样的承诺分配给变量db

我也希望就我的方法提出建议。这是在这里使用承诺的好方法还是有更好的承诺?

是否有必要在return done(null, user)回调中then以遵守常规节点约定,或者在使用promises(bluebird)时不再需要这样做?

2 个答案:

答案 0 :(得分:1)

您可以简单地从create模型的user方法返回承诺。

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;
    })
},

然后,此承诺将以用户的价值解决。所以在其他任何地方你都可以使用这个方法

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函数可以像任何其他函数一样调用,但它将返回一个promise,该promise将使用返回的值进行解析。所以该方法的用法仍然保持不变。

User.create(user)
.then(createdUser => { // do something with user here })

答案 1 :(得分:1)

任何承诺工作最重要的建议是:沟渠回调。

您的代码目前是回调(done())和承诺之间的混合体。不要这样做。仅使用承诺。承诺的关键是你可以从异步函数中返回。你不需要依赖主叫方传递回调。

宣传所有API。强调回归。

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()如何返回不间断的值链。 mySQL连接变成查询结果变成新的用户对象。我不喜欢覆盖现有的实例。避免副作用。

用法很简单。

user.create({
    name: "foo",
    token: 12345,
    type: "user",
    external_id: 67890
}).then(newUser => {
    console.log(newUser);
}).catch(err => {
    console.error(err);
});