【问题标题】:Use mysql with promises in node.js在 node.js 中使用带有 Promise 的 mysql
【发布时间】:2018-06-16 04:45:53
【问题描述】:

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

我用bluebird到promisifymysqljs/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

我也想对我的方法提出建议。这是在这里使用 Promise 的好方法还是有更好的方法?

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

【问题讨论】:

    标签: mysql node.js promise node-mysql


    【解决方案1】:

    对于任何使用 Promise 的工作,最重要的建议是:抛弃回调。

    您的代码目前是回调 (done()) 和承诺之间的混合体。不要那样做。只使用 Promise。 Promise 的关键点是你可以从你的异步函数中返回一些东西。您不需要依赖调用方传入回调。

    承诺所有 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);
    });
    

    【讨论】:

    • 感谢您的回答,它提供了很多见解。我不知道箭头函数中的隐式返回,以及它如何简化承诺。你教我如何简化到最大。
    【解决方案2】:

    您可以简单地从user 模型的create 方法返回一个promise。

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

    【讨论】:

    • 我想同时接受这两个答案。这里真正有趣的是async await
    • 是的,他们让 JS 开发人员的生活更轻松。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2017-04-10
    • 2018-05-26
    相关资源
    最近更新 更多