Node.js全局变量作用域问题

我对Node.js很陌生。在下面的代码中,我从API获取json数据。

let data_json = ''; // global variable

app.get('/',(req,res) => {
    request('http://my-api.com/data-export.json',(error,response,body) => {
        data_json = JSON.parse(body);
        console.log( data_json ); // data prints successfully
    });

    console.log(data_json,'Data Test - outside request code'); // no data is printed
})

data_json 是我的全局变量,我分配了请求函数返回的数据。在该函数中,json数据可以正常打印。但是我尝试在请求函数外部打印相同的数据,但是什么也没打印出来。

我犯了什么错误?

catheone 回答:Node.js全局变量作用域问题

console.log出现在您的请求之前,请查看获取异步数据的方法:回调,promise或async-await。 Nodejs API是异步的(大多数),因此将在request API调用完成之前执行外部console.log。

let data_json = ''; // global variable
app.get('/',(req,res) => {
    let pr = new Promise(function(resolve,reject) {

        request('http://my-api.com/data-export.json',(error,response,body) => {
            if (error) {
                reject(error)
            } else {
                data_json = JSON.parse(body);
                console.log(data_json); // data prints successfully
                resolve(data_json)
            }
        });

    })
    pr.then(function(data) {
      // data also will have data_json
      // handle response here

     console.log(data_json); // data prints successfully

    }).catch(function(err) {
        // handle error here
    })

})

如果您不想创建承诺包装,则可以使用由请求模块团队创建的request-promise-native(使用本机Promises)。

学习callbackspromises,当然还有async-await

,

Node.js无需等待请求解析(从您的API获取数据),而是在外部执行代码,并且不打印任何内容,因为在执行时以及从节点获取数据后仍然没有任何内容。您的api(将需要几毫秒)将在请求中执行代码。这是因为nodejs是异步且非阻塞的语言,这意味着它不会阻塞或暂停代码,直到您的api返回数据为止,它只会继续运行并在获得响应后稍后结束。

在回调函数中执行所需的所有数据操作是一个好习惯,不幸的是,您不能依赖于您拥有的结构。

这是您的代码示例,只是注释了操作顺序:

let data_json = ''; // global variable

app.get('/',res) => {
    //NodeJS STARTS executing this code
    request('http://my-api.com/data-export.json',body) => {
        //NodeJS executes this code last,after the data is loaded from the server
        data_json = JSON.parse(body);
        console.log( data_json );
        //You should do all of your data_json manipluation here
        //Eg saving stuff to the database,processing data,just usual logic ya know
    });

    //NodeJS executes this code 2nd,before your server responds with data
    //Because it doesn't want to block the entire code until it gets a response
    console.log(data_json,'Data Test - outside request code'); 
})

因此,假设您要使用第一个请求中的数据进行另一个请求-您将必须执行以下操作:

request('https://your-api.com/export-data.json',(err,res,body) => {
    request('https://your-api.com/2nd-endpoint.json',body) => {
         //Process data and repeat
     })
    })

如您所见,该模式很快就会变得非常混乱-这被称为回调地狱,因此为了避免产生大量嵌套请求,有一种语法糖可以使此代码看起来更加精美和可维护,它称为异步/等待模式。运作方式如下:

let data_json = ''

app.get('/',async (req,res) => {
    try{
        let response = await request('https://your-api.com/endpoint')
        data_json = response.body
    } catch(error) {
        //Handle error how you see fit
    }
    console.log(data_json) //It will work
})

此代码与您拥有的代码具有相同的功能,但是不同之处在于,您可以一次又一次地创建任意数量的await request(...),而无需嵌套。 唯一的区别是,您必须声明函数是异步async (req,res) => {...},并且所有let var = await request(...)都必须嵌套在try-catch块中。这样,您就可以捕获错误。如果您认为有必要,可以将所有请求放在catch块中。

希望这有所帮助:)

本文链接:https://www.f2er.com/3166641.html

大家都在问