【问题标题】:node js to return global variable set in callback function节点js返回回调函数中设置的全局变量
【发布时间】:2018-10-10 00:50:44
【问题描述】:

我在javascript 中有 2 个函数,我想在回调中设置一个全局变量,然后从我的主函数中返回它。我知道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;

        }
};

【问题讨论】:

  • 究竟是什么不工作,它应该如何工作?
  • results 未定义,因为 javascript 是异步的。 return 语句在回调函数完成之前执行。如何在返回 results 之前等待回调完成(确保在返回之前定义 results)?
  • 结果如何undefinded 而不是""
  • 对不起,这就是我的意思。 results 为空,并且未返回包含来自 resultsCallback 函数中的 html 变量的数据。我设置results 等于html

标签: javascript node.js asynchronous callback return


【解决方案1】:

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

我了解您为什么尝试使用全局变量从回调中获取结果,但它不起作用。

当你的代码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;
    }
};

全局变量可能很危险,您不需要它们。承诺解决你的问题。您可以嵌套尽可能多的回调,但您始终使用resolvePromise 返回值。这是在 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
}

【讨论】:

  • 感谢您的帮助。我了解您的大部分答案,但data 来自getData().then((data)=&gt;{console.log("Table data:",data);}) 的哪里?我应该用回调函数中的变量名填写吗? @GiulioBambini 当我运行它时,它仍然在说:Table Data: undefined
猜你喜欢
  • 1970-01-01
  • 2020-09-11
  • 2021-01-10
  • 1970-01-01
  • 2018-07-15
  • 2022-01-22
  • 2013-05-27
  • 1970-01-01
  • 2017-03-06
相关资源
最近更新 更多