在 node.js 中使用 promise 处理 MySQL 返回值

我有 Python 背景,目前正在迁移到 node.js.由于 node.js 的异步性质,我无法适应它.

I have a python background and is currently migrating to node.js. I have problem adjusting to node.js due to its asynchronous nature.

例如,我试图从 MySQL 函数返回一个值.

For example, I am trying to return a value from a MySQL function.

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

读完之后,我意识到上面的代码不能工作,由于 node.js 的异步特性,我需要返回一个 promise.我不能像 python 那样编写 node.js 代码.如何将 getLastRecord() 转换为返回一个 promise 以及如何处理返回的值?

After some reading up, I realize the above code cannot work and I need to return a promise due to node.js's asynchronous nature. I cannot write node.js code like python. How do I convert getLastRecord() to return a promise and how do I handle the returned value?

其实我想做的就是这样的;

In fact, what I want to do is something like this;

if (getLastRecord() > 20)
{
    console.log("action");
}

如何在 node.js 中以可读的方式完成此操作?

How can this be done in node.js in a readable way?

我想看看在这种情况下如何使用 bluebird 实现 promise.

I would like to see how promises can be implemented in this case using bluebird.

推荐答案

这里有点散,见谅.

首先,假设此代码正确使用了 mysql 驱动程序 API,这里有一种方法可以将其包装为使用本机承诺:

First, assuming this code uses the mysql driver API correctly, here's one way you could wrap it to work with a native promise:

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

所以有一件事:你仍然有回调.回调只是您在将来某个时间点使用其选择的参数传递给某个对象的函数.所以xs.map(fn)中的函数参数,node中看到的(err, result)函数以及promise result和error handlers都是回调.人们将特定类型的回调称为回调",这有点令人困惑,节点核心中使用的 (err, result) 称为继续传递风格",有时称为"nodebacks"由不喜欢它们的人提供.

So one thing: You still have callbacks. Callbacks are just functions that you hand to something to call at some point in the future with arguments of its choosing. So the function arguments in xs.map(fn), the (err, result) functions seen in node and the promise result and error handlers are all callbacks. This is somewhat confused by people referring to a specific kind of callback as "callbacks," the ones of (err, result) used in node core in what's called "continuation-passing style", sometimes called "nodebacks" by people that don't really like them.

至少就目前而言(async/await 最终会出现),无论您是否采用 promise,您几乎都被回调困住了.

For now, at least (async/await is coming eventually), you're pretty much stuck with callbacks, regardless of whether you adopt promises or not.

另外,我会注意到 Promise 不是立即的,显然在这里很有帮助,因为你仍然有一个回调.Promise 仅在您将它们与 Promise.all 和 Promise 累加器(如 Array.prototype.reduce)结合时才真正发挥作用.但它们有时确实闪耀,它们值得学习.

Also, I'll note that promises aren't immediately, obviously helpful here, as you still have a callback. Promises only really shine when you combine them with Promise.all and promise accumulators a la Array.prototype.reduce. But they do shine sometimes, and they are worth learning.

相关文章