node js返回在回调函数中设置的全局变量

时间:2018-04-29 22:14:18

标签: javascript node.js asynchronous callback return

我在javascript中有两个函数,我想在回调中设置一个全局变量,然后从我的main函数返回它。我知道javascript本质上是异步的,那么最好的方法是什么呢?我有以下代码:

var results="";

function getData() {

var sql = require("mssql");
var dbConfig={
        server:"server",
        database: "db",
        user:"user",
        password: "pw"
}




        var conn = new sql.Connection(dbConfig);
        var req = new sql.Request(conn);
        conn.connect(function (err){
                if (err) {
                console.log(err);
                return;
                }


                req.query("SELECT * FROM table",resultsCallback)

                conn.close();
        });

    return results;
}

function resultsCallback (err, recordset) {

        var tableify = require('tableify');

        if (err) {
                console.log(err);
        }
        else {

                var html = tableify(recordset);
                html = html.replace('<table>','');
                html = html.replace('</table>',');
                results=html;

        }
};

1 个答案:

答案 0 :(得分:0)

没有正确的方法可以做到这一点,因为你想做的事情是不对的。您试图在获取之前返回一个值。并且您正在使用全局变量,这可能会对您的代码造成危险。

我理解你为什么要尝试使用全局变量来获取回调的结果,但它无法正常工作。

当您的代码return results;执行时,SQL查询甚至尚未启动,因此返回""

相反,请使用Promise

function getData() {
    return new Promise((resolve, reject) => {
        var sql = require("mssql");
        var dbConfig = {
            server: "server",
            database: "db",
            user: "user",
            password: "pw"
        }
        var conn = new sql.Connection(dbConfig);
        var req = new sql.Request(conn);
        conn.connect(function (err) {
            if (err) {
                console.log(err);
                reject(err);
                return;
            }
            req.query("SELECT * FROM table",
                (err, recordset) => {
                    // Here we call the resolve/reject for the promise
                    try {
                        // If the results callback throws exception, it will be caught in 
                        // the catch block
                        resolve(resultsCallback(err, recordset));
                    }
                    catch (e) {
                        reject(e);
                    }
                }
            );

            conn.close();
        });
    })
}

function resultsCallback(err, recordset) {
    var tableify = require('tableify');
    if (err) {
        console.log(err);
        throw err;
    }
    else {
        var html = tableify(recordset);
        html = html.replace('<table>', '');
        html = html.replace('</table>', '');
        return html;
    }
};

全局变量可能很危险,您不需要它们。承诺解决了你的问题。您可以嵌套任意数量的回调,但始终使用Promiseresolve返回值。这是在JavaScript中执行此操作的标准现代方法。

用法:

getData().then((data)=>{console.log("Table data:",data);})
         .catch((error)=>{console.log("ERROR LOADING SQL:",error);})

或者,在async函数中:

async function doSomethingWithData() {
    console.log("Start loading data.");
    const data = await getData();
    console.log("Done loading data.");
    // your results are in the data variable now
}